0

我想在过程中使用 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 与常量而不是集合一起使用?

我尝试过以下操作:首先,我尝试将直接常量与 'Count' 方法一起使用,但因为它是一种收集方法

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)分配一个范围。请告诉我。

问候

4

3 回答 3

1

不,你不能在这里使用 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;
于 2018-06-15T08:56:29.993 回答
0

我没有使用 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

问候

于 2018-06-24T11:38:59.217 回答
0

只是为了确认你不能使用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您可以通过一种(或其他方法)填充集合,但我们现在正在放弃forall使用 100 个值进行初始化的快速方法的想法,以便我们可以使用它来执行某些任务 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;
于 2018-06-15T19:44:40.067 回答