主要思想是,我想在不事先了解列的情况下实现透视功能。我找到了该here的脚本,但它只用于一列,我想旋转两列。
与使用 PivotImpl 返回流水线结果相比,我具有功能 Pivot :
create or replace function Pivot(p_stmt in varchar2,
p_aggr_function in varchar2 := 'max')
return anydataset
pipelined using PivotImpl;
类型 PivotImpl 是ODCITable(更多here)的实现。
CREATE OR REPLACE TYPE PivotImpl as object
(
ret_type anytype, -- The return type of the table function
stmt varchar2(32767),
aggr_function varchar2(32767),
cur integer,
static function ODCITableDescribe(rtype out anytype,
p_stmt in varchar2)
return number,
static function ODCITablePrepare(sctx out PivotImpl,
ti in sys.ODCITabFuncInfo,
p_stmt in varchar2,
p_aggr_function in varchar2 := 'max')
return number,
static function ODCITableStart(sctx in out PivotImpl,
p_stmt in varchar2)
return number,
member function ODCITableFetch(self in out PivotImpl,
nrows in number,
outset out anydataset) return number,
member function ODCITableClose(self in PivotImpl) return number
)
我的 ODCITablePrepare 如下:
static function ODCITablePrepare(sctx out PivotImpl,
ti in sys.ODCITabFuncInfo,
p_stmt in varchar2,
p_aggr_function in varchar2 := 'max')
return number is
prec pls_integer;
scale pls_integer;
len pls_integer;
csid pls_integer;
csfrm pls_integer;
elem_typ anytype;
aname varchar2(30);
tc pls_integer;
begin
tc := ti.RetType.GetAttrElemInfo(1,
prec,
scale,
len,
csid,
csfrm,
elem_typ,
aname);
--
dbms_output.put_line('Prepare: ' || p_stmt); -- !!!HERE IS MY DEBUG FOR p_stmt VALUES
sctx := PivotImpl(elem_typ,
p_stmp,
p_aggr_function,
null);
return odciconst.success;
end;
在ODCITableClose中,我每次都会使类型无效,并且每次都将强制调用ODCITablePrepare,然后执行我的SELECT。
ODCITableClose 函数的实现是:
member function ODCITableClose(self in PivotImpl) return number is
c integer;
t_id number;
begin
c := self.cur;
dbms_sql.close_cursor(c);
select object_id
into t_id
from user_objects
where object_name = $$PLSQL_UNIT -- name of your type!
and object_type = 'TYPE BODY';
-- invalidating of the type body forces that ODCITableDescribe is executed for every call to the pivot function
-- and we do need that to make sure that any new columns are picked up (= new values for the pivoting column)
dbms_utility.invalidate( t_id );
return odciconst.success;
end;
我有两个选择几乎相等的SELECT,它们的工作原理不同。 在输出的第一个SELECT中,我可以看到 p_stmt 的值为空(来自ODCITablePrepare中的调试)。首先选择:
select *
from table(Pivot(p_stmt => 'select account_number, branch_code, field_name, field_value,field_value_descr
from account_map
group by account_number,branch_code, field_name,field_value,field_value_descr'))
;
在第二种情况下,我使用视图:
create or replace view v_account_map as
select *
from table(Pivot('select account_number, branch_code, field_name, field_value,field_value_descr
from account_map
group by account_number,branch_code, field_name,field_value,field_value_descr'))
;
然后选择:
select *
from v_account_map t
p_stmt的第二个选择值是我传递给Pivot函数的值。
我无法理解的另一个奇怪的想法是为什么在打开 v_account_map 实现我的
时选择*
替换为真实的列名
选择“ ACCOUNT_NUMBER”,“ BRANCH_CODE”,“ A1”,“ A2”,“ A3”
当我添加过滤器以从必须返回结果的视图中进行选择时,结果为空。示例:
select *
from table(Pivot(p_stmt => 'select account_number, branch_code, field_name, field_value,field_value_descr
from account_map
group by account_number,branch_code, field_name,field_value,field_value_descr'))
where account_number = '42342325345452'; --> RETURN 1 row
;
select *
from V_ACCOUNT_MAP t
where account_number = '42342325345452'; --> RETURN 0 rows
在没有过滤器的情况下,两个选择会返回相同的结果。
我的第一个问题是,为什么在第一种情况下ODCITablePrepare不被称为corect,而在第二种情况下称为corect?
第二个问题是为什么我在从ODCITable过滤结果时遇到问题?实际上,问题不仅在于过滤。分组依据也很奇怪。例如,结果必须为 10,20,30,40 。第一次选择结果为 40,40,40,40 ,第二次选择(从视图中)结果仅为 40 。
也许我在实现过程中遗漏了一些东西,但是我可以看到它是什么。
其他信息: 我不确定是不是我的Oracle版本,但是:
OCI: version 11.1
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0