在Oracle SQL
中,有可能use REF
and DEREF
functions將邏輯指針傳遞給存儲在數據庫表中的對象。
但是在PL/SQL
中沒有像指針或引用那樣的東西,所以你需要一個解決方法。
以下是PL/SQL中可能的解決方法的一些方法。我很抱歉代碼中的任何錯誤。它的目的是爲了演示比用於生產的方法。
方法1 - 緩存的訪問方法
通用的想法是通過函數訪問實體哪個緩存結果:
create or replace package EntitytAccess as
procedure GetCompany1(
pCompanyId in number,
pCompany out nocopy pkg_company.typ_company
);
function GetCompany2(
pCompanyId in number
) return pkg_company.typ_company;
procedure ClearCompanyCache;
end;
接包體:
create or replace package body EntitytAccess as
type typ_company_cache is table of pkg_company.typ_company index by number;
var_company_cache typ_company_cache;
procedure GetCompany1(
pCompanyId in number,
pCompany out nocopy pkg_company.typ_company
)
is
begin
if(var_company_cache.exists(pCompanyId))
pCompany := var_company_cache(pCompanyId);
else
pCompany := pkg_company.get(pCompanyId);
var_company_cache(pCompanyId) := pCompany;
end if;
end;
function GetCompany2(
pCompanyId in number
) return pkg_company.typ_company
is
begin
if(not var_company_cache.exists(pCompanyId))
var_company_cache(pCompanyId) := pkg_company.get(pCompanyId);
end if;
return var_company_cache(pCompanyId);
end;
procedure ClearCompanyCache
is
begin
var_company_cache.Delete;
end;
end;
用法:
declare
c pkg_company.typ_company;
e pkg_employee.typ_employee;
begin
EntityAccess.GetCompany2(12345,c);
for e in (select employeeid from employee where companyid=12345)
loop
e := pkg_employee.get(12345, c); -- c passed by reference in out nocopy
-- and c.companyid stored inside e.
pkg_employee.process(e); -- No need to pass company, but inside process()
-- method you need to call either
-- EntityAccess.GetCompany1(e.companyid, var_c)
-- or
-- var_c := EntityAccess.GetCompany2(e.companyid)
end loop;
end;
方法2 - 環境包
因爲包狀態屬於可以使用包變量來保存當前的處理狀態,並在需要的時候引用它一個會話。
create or replace package ProcessEnvironment as
var_current_company pkg_company.typ_company;
-- may be more "global" variables here
end;
/
create or replace package body ProcessEnvironment as
end;
用法:
declare
e pkg_employee.typ_employee;
begin
ProcessEnvironmant.var_current_company := pkg_company.get(12345);
for e in (select employeeid from employee where companyid=12345)
loop
e := pkg_employee.get(12345, ProcessEnvironmant.var_current_company);
-- c passed by reference in out nocopy
-- and c.companyid stored inside e.
pkg_employee.process(e); -- No need to pass company, but inside process()
-- method you references
-- ProcessEnvironmant.var_current_company
-- with appropriate checks
end loop;
end;
混合的方法
似乎在Approach 1
情況下,從集合複製,特別是如果與功能GetCompany2()
訪問的情況。複製構造函數可能速度夠快,但會產生一些開銷。
對於Approach 2
,在業務邏輯功能的代碼中必須存在一些檢查,所以從另一個角度來看它是維護開銷。
爲了解決這兩個問題,你可以使用緩存,但保持包裝內只有一個值:
create or replace package EntitytAccess as
procedure GetCompany(
pCompanyId in number,
pCompany out nocopy pkg_company.typ_company
);
end;
包體:
create or replace package body EntitytAccess as
var_cached_company pkg_company.typ_company;
procedure GetCompany(
pCompanyId in number,
pCompany out nocopy pkg_company.typ_company
)
is
begin
if((var_cached_company is null)
or
(var_cached_company.comanyid != pCompanyId)
)then
var_company_cache := pkg_company.get(pCompanyId);
end if;
pCompany := var_cached_company;
end;
end;
用法:
declare
c pkg_company.typ_company;
e pkg_employee.typ_employee;
begin
EntityAccess.GetCompany(12345,c);
for e in (select employeeid from employee where companyid= c.companyid)
loop
e := pkg_employee.get(c.companyid , c); -- c passed by reference in out nocopy
-- and c.companyid stored inside e.
pkg_employee.process(e); -- No need to pass company, but inside process()
-- method you need to call
-- EntityAccess.GetCompany(e.companyid, var_c)
-- where var_c is company object variable.
end loop;
end;
可能只是添加'c'作爲'pkg_employee.process()'中的另一個'in nocopy'參數? – ThinkJet
這就是我們目前正在做的事情,但是由於有很多函數/過程存在維護開銷,我們可能必須根據邏輯被修改的方式將該參數添加/刪除到函數簽名。如果我們可以在e內部有一個指向c的指針,那將會有很大的幫助。 – nomongo