Oracle 12c - PL/SQL 中的问题
Posted
技术标签:
【中文标题】Oracle 12c - PL/SQL 中的问题【英文标题】:Oracle 12c - Issue in PL/SQL 【发布时间】:2014-08-18 19:51:55 【问题描述】:我有以下代码块:
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
如有任何帮助解决此问题,我们将不胜感激。
【问题讨论】:
问题很容易发现...如果 i.id 不在(子查询)中是无效的。我认为这类似于 if exists select id from table_B where ind_valu = 'y' and i.id = b.id (但我对 12c 并不完全熟悉)。附带问题....为什么将其用作游标?一个没有循环的语句要好得多 pl/sql脚本中还有很多其他的使用游标的代码。应该提到这一点。 你为什么首先使用 PL/SQL?这可以通过一个简单的插入语句更有效地完成:insert into val_table_err select ... from table_a where a.id not in (select id from table_b where ind_val = 'Y')
【参考方案1】:
在任何版本的 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;
当然,这不会像首先过滤掉光标中的贷款那样有效或清晰。
【讨论】:
【参考方案2】:这与您的 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 选择连接算法,而不是自己做一个嵌套循环。
【讨论】:
以上是关于Oracle 12c - PL/SQL 中的问题的主要内容,如果未能解决你的问题,请参考以下文章
PL/SQL Developer 登录 Oracle 12c(转)
由于 Oracle DB 从 12c 升级到 19c,对现有 SQL、PL/SQL 脚本和数据模型有何影响?
“PL/SQL:ORA-02289:序列不存在”在 django 中进行加载数据。数据库是远程oracle 12c
windows64位Oracle Database 12c Release 2安装和PL/SQL Developer配置