Oracle SQL:如何在 FORALL 循环中添加 IF 条件

Oracle SQL : How add IF condition inside FORALL LOOP

我正在尝试将 table 合并到 emp1,如果 select_count 不等于 0。但是我无法在其中添加 select 和 if 语句FORALL 循环。谁能帮我实现这个目标?谢谢

FORALL i IN 1 .. v_emp.LAST
    select count(emp_id) into select_count from emp where emp_id=v_emp(i).emp_id;
    IF select_count <> 0 THEN 
       MERGE INTO emp1 e1 using dual ON(a.id=b.id)
       WHEN MATCHED
         //Update statement
       WHEN NOT MATCHED 
         //Insert statement
    END IF;

以上代码抛出错误信息:

PLS-00201 : Identifier 'I' must be declared.

Oracle PL/SQL FORALL 语句只能覆盖一个 SQL 语句(没有 PL/SQL),因为这基本上命令 Oracle SQL 引擎执行批量操作,SQL 引擎无法 PL/SQL 块。

您似乎想要做的是 FOR 循环。像这样:

FOR i IN 1 .. v_emp.LAST
LOOP
    select count(emp_id) into select_count from emp where emp_id=v_emp(i).emp_id;
    IF select_count <> 0 THEN 
       MERGE INTO emp1 e1 using dual ON(a.id=b.id)
       WHEN MATCHED
         //Update statement
       WHEN NOT MATCHED 
         //Insert statement
    END IF;
END LOOP;

如果您仍希望通过 FORALL 批量执行 MERGE,则首先使用循环来计算计数,然后从 [= 中删除计数为零的条目15=] 集合,所以你可以用它来使用 FORALL

FORALL 显然不是循环结构。它是一个原子语句,因此无法向其中注入条件。

似乎没有必要将FORALL与MERGE结合起来。 MERGE 已经是一个集合操作,它还提供条件。也许您需要做的就是更改您的实现以取消 USING 子句。

您没有描述您尝试实现的所有逻辑,因此以下是一个猜测:您需要对其进行转换以满足您的需要。

 merge into emp1 
 using ( select * from table ( v_emp ) t
         where t.emp_id not in ( select e.emp_id 
                                 from emp e )
      ) q
 on (q.emp_id = emp1.emp_id)
 when not matched then 
      insert ...
 when matched then
      update ...

如果这不能解决您的问题,请编辑您的问题以详细解释您的场景和您尝试实施的业务逻辑。

Thanks for your answer.can you please add a sample code to remove the entries with zero count from the v_emp collection?

从您的评论中挑选,您应该只挑选那些在您的查询中首先出现的计数不为零的记录,而不是在稍后阶段检查它。见下文。

CREATE TABLE emp(emp_NM VARCHAR2(10),
                  emp_id NUMBER,
                  sal NUMBER);
/
INSERT INTO emp VALUES ('X',1,100);                  
INSERT INTO emp VALUES ('A',2,200);
INSERT INTO emp VALUES('B',3,300);
INSERT INTO emp values ('C',4,400);
/
Select * from emp;
/

CREATE OR REPLACE TYPE ep_id IS TABLE OF NUMBER;

/

DECLARE
Type v_emp IS  TABLE OF NUMBER INDEX BY pls_integer;
  emp_var v_emp;

  --Declared a table having emp_id as in your case where you try to get this in a collection v_emp.
  v_ep_id ep_id:=ep_id(1,2,4,5,6);
BEGIN
  ---Query to select only those records whose count is greater than 0.
  SELECT COUNT(emp_id) 
  bulk collect  INTO emp_var
  FROM emp
  --WHERE emp_id IN  (SELECT * FROM TABLE(v_ep_id) ) --< You can use this as well.
  WHERE emp_id MEMBER OF v_ep_id
  GROUP BY emp_id, sal, emp_nm
  HAVING COUNT(emp_id) > 0 ;

  --Here you directly do the merge of the selected records which are not Zero
  FORALL i IN 1 .. emp_var.Count
  MERGE INTO emp1 e1 using dual ON(a.id=b.id)
  WHEN MATCHED
  //Update statement
  WHEN NOT MATCHED
  //Insert statement
  END IF; 

 Exception
 WHEN others then
 raise_application_error(-20001,'Error');
END;