Oracle 12c - PL / SQL中的问题

时间:2014-08-18 19:51:55

标签: sql oracle for-loop oracle12c

我有以下代码块:

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; 

我收到错误PLS-00405: SUBQUERY NOT ALLOWED IN THIS CONTEXT

任何有助于解决此问题的帮助都将不胜感激。

2 个答案:

答案 0 :(得分:2)

您无法在任何版本的Oracle中执行此类NOT IN

NOT IN子句放入游标定义通常是有意义的。假设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');

如果你真的希望在循环中完成检查,你需要一个不同的结构。你可以做点什么

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;

当然,这不会像在游标中过滤贷款一样有效或明确。

答案 1 :(得分:1)

这与您的Oracle版本无关,我在11g中遇到了相同的错误,因为您不能在IF语句中使用NOT IN和子查询。

这是我的测试用例:

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;

此匿名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;
/

尝试这样的事情:

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;
/

它的好处是让oracle选择连接算法,而不是自己做一个嵌套循环。