[英]Enabling and disabling a trigger inside another trigger
我有一张桌子位置
CREATE TABLE Location (
idL INTEGER,
City VARCHAR2(15) NOT NULL,
Street VARCHAR2(35) NOT NULL,
Nation CHAR(6) NOT NULL,
CONSTRAINT PK_idL PRIMARY KEY(idL)
);
还有一个表人
CREATE TABLE Person(
p_Name VARCHAR2(20) NOT NULL,
p_Surname VARCHAR2(20) NOT NULL,
idP INTEGER,
b_Date DATE NOT NULL,
id_PL INTEGER,
CONSTRAINT PK_idP PRIMARY KEY(idP),
CONSTRAINT FK_idPL FOREIGN KEY(id_PL) REFERENCES Location(idL)
);
我“自动”计算主键,如下所示:
CREATE SEQUENCE seq_loc_pk
start with 1
increment by 1;
CREATE OR REPLACE TRIGGER auto_pk_loc
BEFORE INSERT ON Location
FOR EACH ROW
BEGIN
:new.idL := seq_loc_pk.nextval;
END;
/
现在我想插入一个新人的住所(当然在我创建了正确的视图之后),而不是像这样的触发器:
CREATE OR REPLACE TRIGGER newperson
INSTEAD OF INSERT ON Residence
FOR EACH ROW
DECLARE
nl Loc.idL%TYPE;
BEGIN
ALTER TRIGGER auto_pk_loc DISABLE; -- Error
nl := seq_loc_pk.nextval;
:NEW.idL := nl;
INSERT INTO Location VALUES(:NEW.City,:NEW.Street,:NEW.Nation);
INSERT INTO Patient VALUES(:NEW.P_Name,:NEW.P_Surname,:NEW.B_Date,,nl);
ALTER TRIGGER auto_pk_loc ENABLE;
END;
/
我想过禁用和启用触发器 auto_pk_loc 以便它不会无缘无故地创建额外的值,但我认为这不是正确的方法吗? 它是什么? 谢谢谁回答。
您可以通过将其放在execute immedaite
中来做到这一点:
BEGIN
execute immedidate 'ALTER TRIGGER auto_pk_loc DISABLE';
nl := seq_loc_pk.nextval;
:NEW.idL := nl;
INSERT INTO Location VALUES(:NEW.City,:NEW.Street,:NEW.Nation);
INSERT INTO Patient VALUES(:NEW.P_Name,:NEW.P_Surname,:NEW.B_Date,,nl);
execute immedidate 'ALTER TRIGGER auto_pk_loc ENABLE';
END;
/
但这会给你带来各种各样的问题; DDL 提交,所以你必须使它成为一个自治事务,你会遇到并发问题。 最好避免这种情况。
更好的方法是使用returning
子句来获取您刚刚插入的值:
BEGIN
INSERT INTO Location VALUES(:NEW.City,:NEW.Street,:NEW.Nation)
returning idl into nl;
INSERT INTO Patient VALUES(:NEW.P_Name,:NEW.P_Surname,:NEW.B_Date,nl);
END;
/
尽管正如@astentx 指出的那样,您可能希望使用merge
来避免重复位置。 这不支持returing
,因此您必须改用insert+update的某种组合。
最后 - 假设您使用 12c 或更高版本 - 最好使用标识列或序列默认值通过触发器自动生成位置 ID。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.