ForALL 构造:集合范围可以初始化为常量吗?



我想在过程中使用 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 是表中的列。在上面的查询中,如果列的值为 0,则设置 null。

那么是否可以将 ForAll 与常量而不是集合一起使用?

我尝试在下面做: 首先,我尝试使用"计数"方法使用直接常量,但由于它是一种收集方法

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。

FORALL 语句多次运行一个 DML 语句,其中 VALUES 和 WHERE 子句中的不同值。

您处理不同的 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

问候

最新更新