简体   繁体   English

Oracle 12c-PL / SQL中的问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM