我尝试对不同元素(所有者,表)的列表进行排序。 只需一个就可以轻松(并且非常快速!),例如:
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;
/
答案 0 :(得分:2)
至少你在第二种情况下丢失了一个表定义。这句话:
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知道对象实例是相同还是不同,我们需要定义mapping or ordering method for object type。两种方法都不允许,因此需要选择合适的方法。 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;
/
之后,可以在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;
/