【问题标题】:maximum number of recursive SQL levels (50) exceeded超出最大递归 SQL 级别数 (50)
【发布时间】:2026-01-20 15:50:01
【问题描述】:

我想在不使用序列的情况下创建主键,但我不介意使用触发器。 我正在使用 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

谁能告诉我错误在哪里或如何纠正错误?

【问题讨论】:

  • “我想在不使用序列的情况下创建主键” - 你能解释一下吗?
  • 所以你正在插入一个表并且插入会导致一个触发器被调用,这会导致另一行被插入,并且插入会导致一个触发器被调用,这会导致另一行被插入并且插入会导致一个调用触发器,导致插入另一行,插入导致调用触发器,导致插入另一行,插入导致调用触发器,导致插入另一行,插入导致调用触发器导致插入另一行,插入导致调用触发器,导致 ...

标签: oracle plsql triggers


【解决方案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 的两个主要问题:

  1. 它不适用于并发事务

  2. 当你删除当前的“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 过于热衷于删除代码...已修复。感谢您的关注!