ForALL 构造:集合范围可以初始化为常量吗?
ForALL construct: Collection range can be initialized to a constant?
我想在过程中使用 ForAll 构造:
现有的 For 循环是:
max_versions constant number := 100;
FOR i IN 1 ..max_vers
LOOP
l_sql := 'update test_table set p' || i ||'= NULL WHERE p' ||i||'=0 AND condition1=' ||n_input1 ||' AND condition3 = ' || n_condition3;
EXECUTE immediate l_sql;
l_sql := 'update test_table set h' || i ||'= NULL WHERE h ||i||'=0 AND condition1=' ||n_input1 ||' AND condition3 = ' || n_condition3;
EXECUTE immediate l_sql;
END LOOP;
这里 max_vers 是常量 100,p1...p100 和 h1...h100 是 table 中的列。在上面的查询中,如果列的值为 0,则设置 null。
那么是否可以将 ForAll 与常量而不是集合一起使用?
我已尝试执行以下操作:
首先,我尝试将直接常量与 'Count' 方法一起使用,但因为它是 collect
的一种方法
PROCEDURE Test
IS
TYPE MaxVersTab IS TABLE OF number;
maxvers MaxVersTab := 100;
-- Error1
BEGIN
FORALL i IN 1 .. maxvers .count
EXECUTE IMMEDIATE -- Error2 and Error3
'update test_table set p' || i ||'= NULL WHERE p' ||i||'=0 AND condition1=' ||n_input1 || ' AND condition3 =n_input3' USING maxvers(i);
FORALL i IN 1 .. maxversions.count
EXECUTE IMMEDIATE
'update test_table set p' || i ||'= NULL WHERE p' ||i||'=0 AND condition1=' ||n_input1 || ' AND condition3=n_input3' USING maxvers(i);
我收到如下不同的错误:
- 错误 1) 表达式类型错误
- 错误 2) 语句被忽略
- 错误3)这个表达式的类型声明不完整
或格式错误
我的问题是,我们能否为要在 ForAll 中使用的集合分配一个范围(如 100)。请告诉我。
此致
不,你不能在这里使用 FORALL。
The FORALL statement runs one DML statement multiple times, with
different values in the VALUES and WHERE clauses.
您处理不同的 DML 语句,而不是唯一的一个。
您的 DML 语句不同,因为您在其中使用了不同的列。
如果你有一个 DML 语句,你可以这样做:
declare
TYPE MaxVersTab IS TABLE OF number;
maxvers MaxVersTab;
n_input1 varchar2(32767) := 'some_condition_string';
BEGIN
select level
bulk collect into maxvers
from dual
connect by level <= 5;
FORALL i IN 1 .. maxvers .count
EXECUTE IMMEDIATE
'update test_table set p1 = null WHERE p1=:bind_variable1 AND condition1=:bind_variable2' using maxvers(i), n_input1;
end;
只是为了确认您如何不能使用forall
:
您不能将 forall
机制作为生成器单独调用:
begin
forall i in 1..100
insert into demo(id) values (i);
end;
失败:
ORA-06550: line 3, column 38:
PLS-00430: FORALL iteration variable I is not allowed in this context
ORA-06550: line 3, column 9:
PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL
您必须实际使用该集合。
要设置 100 个元素的集合,您必须 extend
它(因此它不能是常量,除非我们编写一个函数来初始化它)。以下运行,但它插入空值,因为我们没有生成任何值:
declare
type number_tt is table of number;
numbers number_tt := number_tt();
begin
numbers.extend(100);
forall i in 1..100
insert into demo(id) values (numbers(i));
end;
您可以通过 select
(或其他一些方法)填充集合,但我们现在正在放弃使用 100 个值快速填充 forall
的想法,以便我们可以用它来执行某个任务 100 次。
declare
type number_tt is table of number;
numbers number_tt := number_tt();
begin
select rownum bulk collect into numbers
from dual connect by rownum <= 100;
forall i in 1..100
insert into demo(id) values (numbers(i));
end;
我没有使用 For 循环,而是使用静态查询,它会一次性更新 h1..h100 和 p1...p100 列。
l_sql := 'UPDATE sh_rpt_temp_peer_final t SET p1= NULLIF(p1, 0),--...NULLIF(p100,0),
h1= NULLIF(h1, 0) --...NULLIF(h100,0),
where condition1=' ||n_input1 || ' AND condition3 =n_input3';
EXECUTE immediate l_sql;
这会将查询执行次数从 200 减少到 1
此致
我想在过程中使用 ForAll 构造:
现有的 For 循环是:
max_versions constant number := 100;
FOR i IN 1 ..max_vers
LOOP
l_sql := 'update test_table set p' || i ||'= NULL WHERE p' ||i||'=0 AND condition1=' ||n_input1 ||' AND condition3 = ' || n_condition3;
EXECUTE immediate l_sql;
l_sql := 'update test_table set h' || i ||'= NULL WHERE h ||i||'=0 AND condition1=' ||n_input1 ||' AND condition3 = ' || n_condition3;
EXECUTE immediate l_sql;
END LOOP;
这里 max_vers 是常量 100,p1...p100 和 h1...h100 是 table 中的列。在上面的查询中,如果列的值为 0,则设置 null。
那么是否可以将 ForAll 与常量而不是集合一起使用?
我已尝试执行以下操作: 首先,我尝试将直接常量与 'Count' 方法一起使用,但因为它是 collect
的一种方法PROCEDURE Test
IS
TYPE MaxVersTab IS TABLE OF number;
maxvers MaxVersTab := 100;
-- Error1
BEGIN
FORALL i IN 1 .. maxvers .count
EXECUTE IMMEDIATE -- Error2 and Error3
'update test_table set p' || i ||'= NULL WHERE p' ||i||'=0 AND condition1=' ||n_input1 || ' AND condition3 =n_input3' USING maxvers(i);
FORALL i IN 1 .. maxversions.count
EXECUTE IMMEDIATE
'update test_table set p' || i ||'= NULL WHERE p' ||i||'=0 AND condition1=' ||n_input1 || ' AND condition3=n_input3' USING maxvers(i);
我收到如下不同的错误:
- 错误 1) 表达式类型错误
- 错误 2) 语句被忽略
- 错误3)这个表达式的类型声明不完整 或格式错误
我的问题是,我们能否为要在 ForAll 中使用的集合分配一个范围(如 100)。请告诉我。
此致
不,你不能在这里使用 FORALL。
The FORALL statement runs one DML statement multiple times, with different values in the VALUES and WHERE clauses.
您处理不同的 DML 语句,而不是唯一的一个。 您的 DML 语句不同,因为您在其中使用了不同的列。
如果你有一个 DML 语句,你可以这样做:
declare
TYPE MaxVersTab IS TABLE OF number;
maxvers MaxVersTab;
n_input1 varchar2(32767) := 'some_condition_string';
BEGIN
select level
bulk collect into maxvers
from dual
connect by level <= 5;
FORALL i IN 1 .. maxvers .count
EXECUTE IMMEDIATE
'update test_table set p1 = null WHERE p1=:bind_variable1 AND condition1=:bind_variable2' using maxvers(i), n_input1;
end;
只是为了确认您如何不能使用forall
:
您不能将 forall
机制作为生成器单独调用:
begin
forall i in 1..100
insert into demo(id) values (i);
end;
失败:
ORA-06550: line 3, column 38:
PLS-00430: FORALL iteration variable I is not allowed in this context
ORA-06550: line 3, column 9:
PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL
您必须实际使用该集合。
要设置 100 个元素的集合,您必须 extend
它(因此它不能是常量,除非我们编写一个函数来初始化它)。以下运行,但它插入空值,因为我们没有生成任何值:
declare
type number_tt is table of number;
numbers number_tt := number_tt();
begin
numbers.extend(100);
forall i in 1..100
insert into demo(id) values (numbers(i));
end;
您可以通过 select
(或其他一些方法)填充集合,但我们现在正在放弃使用 100 个值快速填充 forall
的想法,以便我们可以用它来执行某个任务 100 次。
declare
type number_tt is table of number;
numbers number_tt := number_tt();
begin
select rownum bulk collect into numbers
from dual connect by rownum <= 100;
forall i in 1..100
insert into demo(id) values (numbers(i));
end;
我没有使用 For 循环,而是使用静态查询,它会一次性更新 h1..h100 和 p1...p100 列。
l_sql := 'UPDATE sh_rpt_temp_peer_final t SET p1= NULLIF(p1, 0),--...NULLIF(p100,0),
h1= NULLIF(h1, 0) --...NULLIF(h100,0),
where condition1=' ||n_input1 || ' AND condition3 =n_input3';
EXECUTE immediate l_sql;
这会将查询执行次数从 200 减少到 1
此致