gpt4 book ai didi

oracle - 一种在 PL/SQL 中将按表索引转换为简单表的优雅方法,然后循环遍历每个条目

转载 作者:行者123 更新时间:2023-12-01 13:00:36 24 4
gpt4 key购买 nike

我有两种类型

CREATE OR REPLACE TYPE my_record_type IS OBJECT
(
name varchar2(30)
)
;

CREATE OR REPLACE TYPE my_table_type AS TABLE OF my_record_type

还有一个函数

create or replace my_function return my_table_type
is
type my_hash_type is table of my_record_type index by pls_integer;
v_hash my_hash_type;
v_table my_table_type;
i NUMBER;
begin
-- some business logic here

-- transformation part

v_table := my_table_type();
i := v_hash.first;

while i is not null loop

v_table.extend(1);
v_table(v_table.last) := v_hash(i);
i := v_hash.next(i);

end loop;

-- end transformation part

return v_table;
end;
/

在 10g 中是否有一种优雅的方式来用类似的东西替换转换部分

v_table = CAST( v_hash as  my_table_type )

最佳答案

您可以使用 SELECT my_record_type(column_value) BULK COLLECT INTO v_table from table(v_hash)。但是为了使用它,您必须在函数之外创建 my_hash_type (作为包规范中的 OR 类型,以便 SQL 引擎可见)否则您将收到PLS-00642:SQL 语句中不允许使用本地集合类型

CREATE OR REPLACE TYPE my_hash_type is table OF VARCHAR2(10);
/
set serveroutput on
declare
--type my_hash_type is table OF VARCHAR2(10);
v_hash my_hash_type := my_hash_type();
v_table my_table_type;
i NUMBER;
begin
null ;
for n in 60..75 loop
V_hash.extend(1);
V_hash(v_hash.count) := chr(n) ;
end loop ;

select my_record_type(column_value)
bulk collect into v_table
from table(v_hash) ;

for n in 1..v_table.count loop
dbms_output.put_line( n || ':>' || v_table(n).name);
end loop ;

--PLS-00642: local collection types not allowed in SQL statements

end ;

1:><
2:>=
3:>>
4:>?
5:>@
6:>A
7:>B
8:>C
9:>D
10:>E
11:>F
12:>G
13:>H
14:>I
15:>J
16:>K

看看herehere更多例子等等

时间差异(based on this methodology #s 以百分之一秒为单位)

pl/sql context switch (as described above)
44
42
43
42

loop fill (with type defined outside of block) --A distinct CREATE TYPE on Oracle level

18
18
18
18

loop fill (with type defined within block) --Type created within the Anon. block
23
22
24
22

(以上时间试验是基于此代码的变体:

set serveroutput on
declare
--type my_hash_type is table of my_record_type -index by pls_integer;
v_hash my_hash_type := my_hash_type();
v_table my_table_type;
i NUMBER;
time_before BINARY_INTEGER;
time_after BINARY_INTEGER;
begin

time_before := DBMS_UTILITY.GET_TIME;

for n in 0..15000 loop
V_hash.extend(1);
V_hash(v_hash.count) := my_record_type(n) ;
end loop ;


select my_record_type(column_value)
bulk collect into v_table
from table(v_hash) ;


/*
v_table := my_table_type();
for n in 1..V_hash.count loop
v_table.extend(1);
v_table(v_table.count) := v_hash(n) ;
--dbms_output.put_line( n || ':>' || v_table(n).name);
end loop ;*/
--for n in 1..v_table.count loop
-- dbms_output.put_line( n || ':>' || v_table(n).name);
--end loop ;
time_after := DBMS_UTILITY.GET_TIME;

DBMS_OUTPUT.PUT_LINE (time_after - time_before);
--PLS-00642: local collection types not allowed in SQL statements

end ;
/

因此循环填充快了 50%,但时间差异仍然很小(这里是过早优化和避免某些事情之间的平衡,因为它可能太长了,我建议对您的真实数据进行时间试验以找到最适合的解决方案)。

我能想到的唯一其他“优雅”解决方案是 TREAT ,但您会注意到它需要一个必须在对象类型上的子类型/父类(super class)型解决方案(我无法让它在 Varray/Assoc 上工作。数组类型——希望我错了!)

关于oracle - 一种在 PL/SQL 中将按表索引转换为简单表的优雅方法,然后循环遍历每个条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6254033/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com