小编典典

Oracle-如何强制用户插入多行

sql

我正在学术作业上使用Oracle 11gR2。一个房间必须有3-5个人是有一个限制的。我知道我可以编写一个触发器来检查一个房间是否有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行的触发器?


阅读 158

收藏
2021-05-16

共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语句触发器将遍历集合中的元素,并仅检查这些房间中的人数。

2021-05-16