오라클에 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)
);
내가 hotel
에 삽입 또는 업데이트의 tenants_amount
테이블 stay
의 내용과 일치하는지 확인에 관심이 있어요, 그래서 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
속성의 관리를 저장하기위한 제 2 트리거는 hotel
이다. 이
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;
/
마지막으로, 나는 일부 행 삽입하려고이 관계를 나타내는 테이블이기 때문에이 트리거 화재 때 DML 작업이 stay
에 만들어진 :
INSERT INTO hotel VALUES (1,'Hotel 1',0);
INSERT INTO tourist VALUES (1, 'Tourist 1');
INSERT INTO stay VALUES (1, 1);
가 그리고 나는 호텔 트리거에서 오류가 : stay
의 트리거가 발사 될 때이 호텔의 tenants_amount
증가하는 시도 :
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'
이 일어나는 것이다 id=1
은이 트리거가 hotel
인 트리거입니다. hotel
트리거는 tenants_amount
이 stay
의 내용과 일치하는지 확인하지만 변경 내용은 여전히 표시되지 않으며 행을 찾지 못합니다. tenants_amount
은 0이어야하지만 hotel
의 업데이트는 1로 설정됨을 의미합니다.
이 문제를 어떻게 해결할 수 있는지 알고 싶습니다.
스타일 기록해 둡니다 당신이 INSERT''에 세 개의 서로 다른 트리거를 작성해야'UPDATE'와'DELETE', 대신'IF INSERTING'과 하나 하나의 - al. 내부. – kmkaplan
검색하는 동안 값을 계산할 때 성능 문제가있는 것으로 입증되지 않는 한 또는 계산할 때까지 계산할 수있는 데이터를 저장하는 것이 가장 좋습니다. 그렇게하면 트리거를 만들지 않고도 항상 * 정확한 데이터를 얻을 수 있습니다. (또는 다른 말로하면, 불일치가 발생할 수있는 기회를 소개하는 것은 계산 가능한 데이터를 저장하는 것입니다) –