【发布时间】:2022-11-03 16:40:11
【问题描述】:
我正在尝试在具有动态 SQL 的循环内进行批量收集,并根据来自循环的输入执行多次,然后插入表中(插入 193234 条记录大约需要 4 分钟)。 为了尝试不同的不同方法,我想在循环内对 select 使用批量收集并在该循环的每次迭代中填充一个集合让我们说第一次迭代给出 10 行,然后第二次给出 0 行,第三次返回 15 行,然后是集合应该在循环结束时保存 15 条记录。 退出循环后,我将使用 forall 与我在循环内部填充的集合一起执行插入操作,而不是为循环内部的每次迭代执行插入操作。
下面是一个类似于应用程序的示例代码,我只是使用不同的表格来简化问题。
create table test_tab as select owner, table_name, column_name from all_tab_cols where 1=2;
create or replace procedure p_test
as
l_sql varchar2(4000);
type t_tab is table of test_tab%rowtype index by pls_integer;
l_tab t_tab;
l_tab1 t_tab;
l_cnt number := 0;
begin
for i in (with tab as (select 'V_$SESSION' table_name from dual
union all
select 'any_table' from dual
union all
select 'V_$TRANSACTION' from dual
union all
select 'test_table' from dual
)
select table_name from tab )
loop
l_sql := 'select owner, table_name, column_name from all_tab_cols where table_name = '''||i.table_name||'''';
-- dbms_output.put_line(l_sql );
execute immediate l_sql bulk collect into l_tab;
dbms_output.put_line(l_sql ||' > '||l_tab.count);
l_cnt := l_cnt +1;
if l_tab.count<>0
then
l_tab1(l_cnt) := l_tab(l_cnt);
end if;
end loop;
dbms_output.put_line(l_tab1.count);
forall i in indices of l_tab1
insert into test_tab values (l_tab1(i).owner, l_tab1(i).table_name, l_tab1(i).column_name);
end;
它只在 test_tab 表中插入 2 行,而根据我的系统,它应该插入 150 行。
select owner, table_name, column_name from all_tab_cols where table_name = 'V_$SESSION' > 103
select owner, table_name, column_name from all_tab_cols where table_name = 'any_table' > 0
select owner, table_name, column_name from all_tab_cols where table_name = 'V_$TRANSACTION' > 47
select owner, table_name, column_name from all_tab_cols where table_name = 'test_table' > 0
2
以上是我系统中的 DBMS_OUTPUT 如果示例表名在您的数据库中不存在,您可以在循环中更改表名。
甲骨文版本——
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
【问题讨论】:
-
1.你在
l_sql里面用的不是动态SQL,应该是静态SQL,因为没有动态身份标识在里面。所以应该是select owner, table_name, column_name bulk collect into l_tab from all_tab_cols where table_name = i.table_name。 2.如果不需要任何PL/SQL处理,不要来回移动数据。使用insert into test_tab (<columns>) select <columns> from all_tab_cols where table_name in (<subquery that generates table names>) -
只是想知道:为什么不直接将行插入 TEST_TAB(从 ALL_TAB_COLS 中选择)? IE。使用纯 SQL 而不是 PL/SQL?
-
@astentx,感谢您的回复我知道我当前的 SQL 不需要动态 SQL 我只是在这里使用它来简化示例,但在实际过程中 SQL 是动态的,目前它被写为 insert into table select * from table only 我只是想做不同的事情,因为当前的方法需要时间只插入 193234 条记录。
-
因此,您真正的动态 SQL 使用动态表名和/或列(不是过滤值),并且您希望根据外部传递的此参数插入一些内容,对吗?
-
@Littlefoot,感谢您的回复,目前它只是按照您在评论中所说的那样写,但是插入需要时间,所以我想尝试另一种方法来看看它是否有帮助:)