我在学术作业中使用Oracle 11gR2。有一个限制,一个房间必须有3-5人。我知道我可以写一个这样的Trigger来检查一个房间是否有超过5个人:
CREATE TABLE People
(
PID INTEGER PRIMARY KEY
);
CREATE TABLE Room
(
RID INTEGER PRIMARY KEY
);
CREATE TABLE Living
(
RID INTEGER,
PID INTEGER,
CONSTRAINT Living_PK PRIMARY KEY (RID, PID),
CONSTRAINT Living_FK_RID FOREIGN KEY (RID) REFERENCES Room(RID),
CONSTRAINT Living_FK_PID FOREIGN KEY (PID) REFERENCES People(PID)
);
CREATE OR REPLACE TRIGGER Living_BIU
BEFORE INSERT OR UPDATE ON Living
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
Count NUMBER;
BEGIN
SELECT COUNT(*)
INTO Count
FROM Living
WHERE RID = :NEW.RID;
IF(Count > 5)
THEN
RAISE_APPLICATION_ERROR(-20002, 'Too many people in a room.');
END IF;
END Living_BI;
但我无法检查数字是否小于3,因为我无法在Living中插入任何内容。所以我的问题是如何创建一个强制用户一次插入3行以上且少于5行的触发器?
答案 0 :(得分:1)
使用标准前言,这不是你在现实世界中真正做到这一点的方式......
您实际上需要在此处使用语句级触发器。如果你不介意每次都检查每个房间的性能
CREATE OR REPLACE TRIGGER Living_AIUD
AFTER INSERT OR UPDATE OR DELETE
ON Living
DECLARE
Count NUMBER;
BEGIN
FOR x IN (SELECT rid, count(*) cnt
FROM living
GROUP BY rid
HAVING COUNT(*) < 3)
LOOP
RAISE_APPLICATION_ERROR(-20002, 'Too few people in room ' || x.rid);
END LOOP;
END Living_AIUD;
如果您不想每次都为每个房间检查一次,那么您需要一个包含rid
值集合的包,一个初始化集合的before语句触发器和一个行级触发器将:new.rid
值添加到集合中。然后,您的after语句触发器将遍历集合中的元素,并检查这些房间中的人数。