我尝试对不同元素(所有者,表)的列表进行排序。只需一个,就很容易(并且非常快!),例如:
declare TYPE tbl_list IS TABLE OF VARCHAR2(64); l_tables tbl_list; i number; begin l_tables:=tbl_list(); for i in 1..100000 loop l_tables:= l_tables MULTISET UNION DISTINCT tbl_list('myTable'); end loop; for i in l_tables.first.. l_tables.last loop dbms_output.put_line(l_tables(i)); end loop; end; /
我尝试对列表进行同样的操作,但是失败了:
create or replace TYPE tbl_list2 IS OBJECT (l_owner VARCHAR2(64),l_name VARCHAR2(64)); declare l_object tbl_list2; i number; begin l_object:=tbl_list2('',''); for i in 1..100000 loop l_object:= l_object MULTISET UNION DISTINCT tbl_list2('myOwner','MyTable'); end loop; for i in l_object.first.. l_object.last loop dbms_output.put_line(l_object(i)); end loop; end; /
但是我发现了以下问题: PLS-00306:调用“ MULTISET_UNION_DISTINCT”时参数的数量或类型错误
目的是要列出所有不同的(所有者,表)列表,我当然不在乎是否有其他想法。
解决方案当然是两个词中的一个词的串联,但是我想找到更优雅的方法!
编辑 @ThinkJet:
我喜欢您的解决方案。比我肮脏的解决方案还优雅。但是,您的解决方案比我的解决方案慢70倍!那么,我们如何才能汇聚一个优雅的蚂蚁速度解决方案呢?
这是我肮脏的一个:
declare TYPE tbl_list IS TABLE OF VARCHAR2(64); l_tables tbl_list; i number; begin l_tables:=tbl_list(); for i in 1..100000 loop l_tables:= l_tables MULTISET UNION DISTINCT tbl_list('myOwner'||','||'myTable'); end loop; for i in l_tables.first.. l_tables.last loop dbms_output.put_line('OWNER='||REGEXP_SUBSTR(l_tables(i),'[^,]+', 1, 1)); dbms_output.put_line('TABLE='||REGEXP_SUBSTR(l_tables(i),'[^,]+', 1, 1)); end loop; end;
/
至少在第二种情况下,您丢失了表定义。这个说法:
create or replace TYPE tbl_list2 IS OBJECT (l_owner VARCHAR2(64),l_name VARCHAR2(64));
仅声明对象(或记录)类型,而不声明表。
因此,您需要分两个步骤进行操作:
create or replace TYPE tbl_list_rec IS OBJECT (l_owner VARCHAR2(64),l_name VARCHAR2(64)); / create or replace TYPE tbl_list2 as table of tbl_list_rec; /
之后,您需要在脚本中进行一些语法更正:
declare l_object tbl_list2; i number; begin -- for list initialization it must be filled with constructed objects l_object := tbl_list2( tbl_list_rec('','') ); for i in 1..100000 loop -- 1. select values to variable -- 2. Fix constructor for list select l_object MULTISET UNION DISTINCT tbl_list2(tbl_list_rec('myOwner','MyTable')) into l_object from dual; end loop; for i in l_object.first .. l_object.last loop -- output separate fields, there are now default conversion from -- user-defined objects to varchar2. dbms_output.put_line(l_object(i).l_owner || ',' || l_object(i).l_name); end loop; end; /
由于上下文切换数量众多,上述解决方案相对较慢。但是,如果没有一些额外的工作,就不能直接在PL / SQL中完成复杂对象类型实例的比较。 为了使Oracle知道对象实例是相同还是不同,我们需要为对象类型定义映射或排序方法。两种方法都不允许,因此需要选择适当的一种。MAP方法的执行速度更快,在我们的案例中无需排序,因此请执行以下操作:
create or replace TYPE tbl_list_rec2 AS OBJECT ( l_owner VARCHAR2(64), l_name VARCHAR2(64), map member function get_key return varchar2 ); /
执行:
create or replace TYPE BODY tbl_list_rec2 AS map member function get_key return varchar2 is begin return l_owner||chr(1)||l_name; end; end; /
之后,可以像varchar2问题中第一个示例中一样简单地在PL / SQL代码中测试对象的相等性:
varchar2
declare l_object tbl_list2a; i number; begin l_object := tbl_list2a( tbl_list_rec2('','') ); for i in 1..100000 loop l_object := l_object MULTISET UNION DISTINCT tbl_list2a(tbl_list_rec2('myOwner','MyTable')); end loop; for i in l_object.first.. l_object.last loop dbms_output.put_line(l_object(i).l_owner || ',' || l_object(i).l_name); end loop; end; /