我想在不使用序列的情况下创建主键,但我不介意使用触发器。 我正在使用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
有谁能告诉我错误在哪里或我如何纠正错误?
答案 0 :(得分:4)
你在插入"之前正在做#34;触发。在这样的触发器中,您不会插入到同一个表中 - 否则,您将获得无限循环。只需赋值给变量值:
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
变量中插入正确的值。
我只想说序列存在是有原因的,你应该将它们用于此目的。试图模仿他们的功能可能会导致错误。
答案 1 :(得分:4)
你为什么要这样做?
如果您需要自动生成的序列号,请使用序列。
SELECT MAX(id) + 1
的两个主要问题:
它不适用于并发事务
删除当前“max”
答案 2 :(得分:1)
插入dept2
时会触发您的触发器,然后在insert
上执行dept2
,这会导致触发器在无限递归中重新触发等。
你不应该明确地调用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 ;
/