问题
I am using Oracle 11gR2 on an Academic Assignment. There is a constraint which a room must have 3 - 5 people. I know that I can write a Trigger like this to check if a room has more than 5 people:
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;
But I can not check if the number is lesser than 3 because then I can not insert any things into Living. So my question is how can I create a trigger that force user to insert more than 3 rows and less than 5 rows at a time?
回答1:
With the standard preface that this isn't how you would really do this sort of thing in the real world...
You would realistically need to use a statement-level trigger here. If you don't mind the performance hit of checking every room every time
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;
If you don't want to check this for every room every time, you'd need a package with a collection of rid
values, a before statement trigger that initialized the collection, and a row-level trigger that added the :new.rid
value to the collection. Your after statement trigger would then iterate over the elements in the collection and check the number of people in just those rooms.
来源:https://stackoverflow.com/questions/23223656/oracle-how-to-force-user-to-insert-multiple-row