【发布时间】:2021-05-27 16:30:48
【问题描述】:
我有一张桌子位置
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;
/
现在我想为一个新人插入 residence(当然是在我创建了正确的视图之后),而不是像这样的触发器:
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 以便它不会无缘无故地创建额外的值,但我认为这不是正确的方法吗?它是什么?谢谢谁回答。
【问题讨论】:
-
在另一个触发器中启用一个触发器是行不通的,原因有几个。您能否简单地将
if语句放在auto_pk_loc触发器中,以便仅在:new.idL is null时分配一个新值,以便如果任何insert语句为使用该值的键指定显式值?那将是最简单的选择。 -
如果相同的位置(城市、街道、国家)已经存在怎么办?您可以在不禁用触发器的情况下将
merge与when not matched then insert一起使用(但首先您需要有一些唯一的键来匹配)。 -
假设您禁用了触发器,此时另一个会话将一条记录插入到您的表中 - 它会失败。禁用的触发器被全局禁用。
标签: sql oracle oracle11g triggers