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;
我正在尝试将 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;