1

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

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:必须声明标识符“I”。

4

3 回答 3

2

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 ...

如果这不能解决您的问题,请编辑您的问题以详细说明您的方案和您尝试实现的业务逻辑。

于 2018-05-13T06:54:18.903 回答
0

Oracle PL/SQLFORALL语句只能覆盖一条 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;

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

于 2018-05-12T22:42:48.317 回答
0

感谢您的回答。您能否添加一个示例代码以从 v_emp 集合中删除计数为零的条目?

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

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;
于 2018-05-14T06:36:20.037 回答