这似乎是解析器感到困惑。如果完全删除AS ROOT
,则会恢复为预期的PLS-00405: subquery not allowed in this context
错误。不知道它为什么会混淆 - 你可以单独运行这个查询 - 但是因为你不能做你正在尝试的东西,所以它可能不值得担心太多。
你的子查询也有三列,并且将返回多行,因此与当前行的标量PARENT_ID是行不通的比较。你可以单独运行你的子查询,并选择你真正感兴趣的值到一个局部变量中,然后检查它。
但是,您有一个before-insert触发器,并且您正在查询触发器违反的表,因此无论如何,当您尝试插入时(或者至少,如果尝试插入多个行一次)。
如果我理解你想达到什么样的,你可以使用后,INSERT触发器来代替:
create or replace trigger check_cycle
after insert or update on departments
declare
l_hascycle pls_integer;
begin
select max(connect_by_iscycle)
into l_hascycle
from departments
start with parent_id is null
connect by nocycle prior id = parent_id;
if l_hascycle = 1 then
raise_application_error(-20000, 'Sorry.');
end if;
end;
/
这使用CONNECT_BY_ISCYCLE pseudocolumn,这将是所有行零,如果没有自行车,和一个循环的任何列。选择和检查的该max()
意味着你将在当地l_hascycle
变量具有0或1的单个值,你可以用它来决定是否抛出异常。
上插入现有非循环的数据,如顶部的几个测试行:
ID PARENT_ID NAME
---------- ---------- ------------
1 Test
2 1 Test
...其中第一个新行是OK,第二会导致一个循环:
insert into departments (id, parent_id, name) values (3, 2, 'OK');
1 row inserted.
insert into departments (id, parent_id, name) values (2, 3, 'Cycles');
ORA-20000: Sorry.
ORA-06512: at "SCHEMA.CHECK_CYCLE", line 11
ORA-04088: error during execution of trigger 'SCHEMA.CHECK_CYCLE'
第一插入仍然有效(但尚未提交),第二次是隐式回滚:
select * from departments:
ID PARENT_ID NAME
---------- ---------- ------------
1 Test
2 1 Test
3 2 OK
由于start with
子句的原因,这将无法捕获未连接到现有树的数据中的循环,最终导致空父项;因此对于数据检验,可以插入4,5和5,4而不引发异常,因为没有从4或5到具有空父母的行的路由。但这是一个不同的问题,你可能需要单独测试。
这还不能看到其他会话未提交的修改数据,所以它可能是两个会议同时插入均有效,但仍然会形成一次循环都被提交的行。
你有没有尝试从查询中删除所有“为” S? – Hawk
当然。没有帮助。 –
你应该问自己这个部分是否需要在你的查询中,因为它没有在任何地方使用(据我所知)。 此外 - 你应该失去'new'关键字旁边的冒号,这是没有必要的。 –