超出最大递归 SQL 级别数 (50)
Posted
技术标签:
【中文标题】超出最大递归 SQL 级别数 (50)【英文标题】:maximum number of recursive SQL levels (50) exceeded 【发布时间】:2014-12-18 02:36:06 【问题描述】:我想在不使用序列的情况下创建主键,但我不介意使用触发器。 我正在使用 oracle 11gR2。 我的脚本包含以下内容。 一种。创建表(dept2) 湾。插入样本数据 C。创建触发器(查找最大值,加 1,插入) d。插入另一条记录(触发器应该触发) 它给出了上述错误。 下面是我的脚本。
drop table dept2 ;
create table dept2
(
deptno number(2),
dname varchar2(20),
mgr number(3)
) ;
insert into dept2 values (11, 'a', 23) ;
insert into dept2 values (12, 'b', 24) ;
select * from dept2 ;
CREATE OR REPLACE TRIGGER trig_deptno2
BEFORE INSERT ON dept2
FOR EACH ROW
DECLARE v_deptno NUMBER(2) ;
BEGIN
SELECT MAX(deptno) INTO v_deptno
FROM dept2 ;
INSERT INTO dept2 VALUES
((v_deptno + 1), :NEW.dname, :NEW.mgr) ;
END trig_deptno2 ;
/
SHOW ERR
L
insert into dept2 (dname, mgr) values ('d', 24) ;
select * from dept2 ;
L
谁能告诉我错误在哪里或如何纠正错误?
【问题讨论】:
“我想在不使用序列的情况下创建主键” - 你能解释一下吗? 所以你正在插入一个表并且插入会导致一个触发器被调用,这会导致另一行被插入,并且插入会导致一个触发器被调用,这会导致另一行被插入并且插入会导致一个调用触发器,导致插入另一行,插入导致调用触发器,导致插入另一行,插入导致调用触发器,导致插入另一行,插入导致调用触发器导致插入另一行,插入导致调用触发器,导致 ... 【参考方案1】:您正在执行“插入前”触发器。在这样的触发器中,您不要插入到同一个表中——否则,您会得到一个无限循环。只需分配给变量值:
CREATE OR REPLACE TRIGGER trig_deptno2
BEFORE INSERT ON dept2
FOR EACH ROW
DECLARE v_deptno NUMBER(2) ;
BEGIN
SELECT coalesce(MAX(deptno) + 1, 1) INTO :new.deptno
FROM dept2 ;
END trig_deptno2 ;
触发器完成后,它会从new
变量中插入正确的值。
我只想说,序列的存在是有原因的,您应该为此目的使用它们。试图模仿它们的功能可能会导致错误。
【讨论】:
扩展这个以讨论为什么这种方法存在很大问题(性能、多用户系统等)会非常有用【参考方案2】:你为什么要这么做?
如果您需要自动生成的序列号,请使用序列。
SELECT MAX(id) + 1
的两个主要问题:
它不适用于并发事务
当你删除当前的“max”时它会重复数字
【讨论】:
【参考方案3】:您的触发器在插入到dept2
时触发,然后在dept2
上执行insert
,这会导致触发器重新触发,等等。
您不应该显式调用insert
- 只需更新:NEW
记录,一旦触发器完成,更新的记录将插入到表中:
CREATE OR REPLACE TRIGGER trig_deptno2
BEFORE INSERT ON dept2
FOR EACH ROW
DECLARE v_deptno NUMBER(2) ;
BEGIN
SELECT MAX(deptno) + 1 INTO :NEW.deptno
FROM dept2;
END trig_deptno2 ;
/
【讨论】:
您的SELECT
语句缺少FROM
子句。
嗨 Mureinik,你真是个天才。我没想到会那么容易。仅缺少“from”关键字,但这不是问题。你的想法运作良好。非常感谢。
@JustinCave 过于热衷于删除代码...已修复。感谢您的关注!以上是关于超出最大递归 SQL 级别数 (50)的主要内容,如果未能解决你的问题,请参考以下文章