同时触发使插入和更新变得困难

时间:2017-04-23 06:42:31

标签: oracle triggers simultaneous mutating-table

我在Oracle中有4个表:hoteltouriststayleavestay表与入住酒店的游客有关,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。

我想知道如何解决这个问题。

1 个答案:

答案 0 :(得分:0)

触发stay_trg AFTER INSERT而不是BEFORE INSERT