我在Oracle中有4个表:hotel
,tourist
,stay
,leave
。 stay
表与入住酒店的游客有关,leave
表存储旅游者离开酒店的日期信息。
CREATE TABLE hotel (
id NUMBER(5),
name VARCHAR2(50),
tenants_amount NUMBER(3)
);
ALTER TABLE hotel ADD CONSTRAINT hotel_c1
CHECK(tenants_amount>=0 AND tenants_amount<=100);
CREATE TABLE tourist (
id NUMBER(5),
name VARCHAR2(50)
);
CREATE TABLE stay (
tourist_id NUMBER(5),
hotel_id NUMBER(5)
);
CREATE TABLE leave (
departure_date DATE,
hotel_id NUMBER(5),
tourist_id NUMBER(5)
);
我有兴趣检查tenants_amount
上的插入或更新的hotel
是否与表stay
的内容一致,所以我为{{写了这个触发器1}}
hotel
我还写了第二个触发器,用于存储CREATE OR REPLACE TRIGGER hotel_trg
BEFORE INSERT OR UPDATE ON hotel
FOR EACH ROW
DECLARE
amount NUMBER(3);
BEGIN
SELECT COUNT(tourist_id) INTO amount FROM stay WHERE hotel_id=:NEW.id GROUP BY hotel_id;
IF :NEW.tenants_amount!=amount THEN
RAISE_APPLICATION_ERROR(-20001, 'Specified tenants amount differs from the system records');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
IF :NEW.tenants_amount!=0 THEN
RAISE_APPLICATION_ERROR(-20001, 'Specified tenants amount differs from the system records');
END IF;
END;
/
的信息和leave
tenants_amount
属性的管理。在hotel
上进行DML操作时会触发此触发器,因为它是表示此关系的表格
stay
最后,我尝试插入一些行:
CREATE OR REPLACE TRIGGER stay_trg
BEFORE INSERT OR UPDATE OR DELETE ON stay
FOR EACH ROW
DECLARE
amount NUMBER(3);
BEGIN
IF INSERTING THEN
SELECT tenants_amount INTO amount FROM hotel WHERE id=:NEW.hotel_id;
UPDATE hotel SET tenants_amount=amount+1 WHERE id=:NEW.hotel_id;
END IF;
IF UPDATING AND :NEW.hotel_id!=:OLD.hotel_id THEN
SELECT tenants_amount INTO amount FROM hotel WHERE id=:OLD.hotel_id;
UPDATE hotel SET tenants_amount=amount-1 WHERE id=:OLD.hotel_id;
INSERT INTO leave VALUES (SYSDATE, :OLD.hotel_id, :OLD.tourist_id);
SELECT tenants_amount INTO amount FROM hotel WHERE id=:NEW.hotel_id;
UPDATE hotel SET tenants_amount=amount+1 WHERE id=:NEW.hotel_id;
END IF;
IF DELETING THEN
SELECT tenants_amount INTO amount FROM hotel WHERE id=:OLD.hotel_id;
UPDATE hotel SET tenants_amount=amount-1 WHERE id=:OLD.hotel_id;
INSERT INTO leave VALUES (SYSDATE, :OLD.hotel_id, :OLD.tourist_id);
END IF;
END;
/
我从酒店触发器中得到错误:
INSERT INTO hotel VALUES (1,'Hotel 1',0);
INSERT INTO tourist VALUES (1, 'Tourist 1');
INSERT INTO stay VALUES (1, 1);
这就是:当ERROR at line 1:
ORA-20001: Specified tenants amount differs from the system records
ORA-06512: at "HOTEL_TRG", line 11
ORA-04088: error during execution of trigger 'HOTEL_TRG'
ORA-06512: at "STAY_TRG", line 6
ORA-04088: error during execution of trigger 'STAY_TRG'
的触发器被触发时,它会尝试使用stay
增加酒店的tenants_amount
,这是一个触发{{{}的触发器的更新1}}。 id=1
的触发器会检查hotel
是否与hotel
的内容一致,但更改仍然不可见,并且找不到任何行。这意味着tenants_amount
应为0,但stay
上的更新将其设置为1。
我想知道如何解决这个问题。
答案 0 :(得分:0)
触发stay_trg
AFTER INSERT
而不是BEFORE INSERT