[英]Oracle 12c - Issue in PL/SQL
I have the following block of code: 我有以下代码块:
DECLARE
CURSOR c_cursor IS
SELECT *
FROM table_a;
FOR i IN c_cursor LOOP
IF i.id NOT IN (SELECT id FROM table_b WHERE ind_val='Y')
THEN
BEGIN
INSERT INTO val_table_err
VALUES (''ERROR:id''|| i.id,
1,
1,
NULL,
1,
i.type_cd);
END;
END IF;
END LOOP;
I am getting the error PLS-00405: SUBQUERY NOT ALLOWED IN THIS CONTEXT
我收到错误
PLS-00405: SUBQUERY NOT ALLOWED IN THIS CONTEXT
Any help to resolve this issue would be appreciated. 解决此问题的任何帮助将不胜感激。
You can't do a NOT IN
like that in any version of Oracle. 在任何版本的Oracle中,您都不能像这样进行
NOT IN
。
It would generally make sense to put the NOT IN
clause into your cursor definition. 通常将
NOT IN
子句放入游标定义中是有意义的。 Assuming that NOT IN
rather than NOT EXISTS
is the more efficient approach, something like this would work. 假设
NOT IN
而非NOT EXISTS
是更有效的方法,则类似的方法将起作用。
CURSOR c_cursor IS
SELECT *
FROM table_a a
WHERE a.id NOT IN (SELECT b.id
FROM table_b b
WHERE ind_val = 'Y');
If you really want the check to be done within the loop, you'd need a different construction. 如果您确实希望在循环中完成检查,则需要使用其他结构。 You could do something like
你可以做类似的事情
FOR i IN c_cursor
LOOP
SELECT COUNT(*)
INTO l_cnt
FROM table_b b
WHERE b.id = i.id
AND b.ind_val = 'Y';
IF( l_cnt = 0 )
THEN
<<do something>>
END IF;
END LOOP;
Of course, this won't be as efficient or as clear as filtering out the loans in the cursor in the first place. 当然,这不会像首先过滤掉游标中的贷款那样有效或清晰。
This is nothing related to your Oracle version, I got the same error in 11g, because you can't use NOT IN and a subquery inside an IF statement. 这与您的Oracle版本无关,我在11g中遇到了相同的错误,因为您不能在IF语句中使用NOT IN和子查询。
Here's my test case: 这是我的测试用例:
create table table_a (idA number);
create table table_b (idB number);
insert into table_a values(1);
insert into table_a values(2);
insert into table_b values(1);
commit;
This anonymous pl/sql block gets the same error as yours: 此匿名pl / sql块与您的错误相同:
DECLARE
i number;
CURSOR c_cursor IS
SELECT idA
FROM table_a;
begin
FOR i IN c_cursor LOOP
IF i NOT IN (SELECT idB FROM table_b)
THEN
dbms_output.put_line(i);
END IF;
END LOOP;
end;
/
Try something like this instead: 尝试这样的事情:
DECLARE
CURSOR c_cursor IS
SELECT idA, idB
FROM table_a a left join table_b on idA=idB;
i c_cursor%rowtype;
begin
FOR i IN c_cursor LOOP
IF i.idB is null
THEN
dbms_output.put_line(i.idA);
END IF;
END LOOP;
end;
/
It has the benefit of letting oracle choose the join algorithm, instead of doing a nested loop yourself. 这样做的好处是让oracle选择连接算法,而不是自己进行嵌套循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.