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);

我收到如下不同的错误:

我的问题是,我们能否为要在 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

此致