2017-10-26 7 views
0

학교 지정, 데이터베이스 구축에 대한 작업. 내 데이터베이스는 사진 비즈니스 모델입니다. 그것의 대부분은 간단하지만 지금은 붙어 있습니다. 따라서 내 모델에는 Photography_Availability Entity (Ph_Av)가 있으며 사진가가 예약되거나 사용 불가능할 때마다 사진사가 사용할 수없는 날짜 및 시간 간격 (Available_Date, Start_Time_Available, Fin_Time_Available)이있는 해당 항목이 있습니다. 이 모든 것은 오라클 모델러 내의 DateTime 데이터 유형입니다. 나는 누군가가 사진 작가를 일정을 잡으려고 할 때마다 그들이 사용 가능한지 아닌지 (적절한 날짜와 시간 간격 동안) 점검 할 방아쇠를 구현하려고합니다.Oracle 트리거 : 어떻게 구현합니까?

이 작가가 이미 3 오후 5시 누군가가이시에서 오후 4시 사이에 같은 작가를 예약하려는 시도 사이에 예약되었습니다 말 것을 분명이 충돌
CREATE OR REPLACE TRIGGER SAFE_SCHEDULE 
BEFORE INSERT OR UPDATE ON PH_AV 
FOR EACH ROW 
DECLARE 
    ID VARCHAR(20) := NULL; 
    AV_DATE DATE := NULL; 
    START_TIME DATE := NULL; 
    FIN_TIME DATE := NULL; 
BEGIN 
    SELECT PHOTOGRAPHER_ID INTO ID FROM PH_AV WHERE PHOTOGRAPHER_ID = :NEW.PHOTOGRAPHER_ID ; 

    SELECT AVAILABILITY_DATE INTO AV_DATE FROM PH_AV WHERE PHOTOGRAPHER_ID = :NEW.PHOTOGRAPHER_ID; 

    SELECT START_TIME_AVAIL INTO START_TIME FROM PH_AV WHERE PHOTOGRAPHER_ID = :NEW.PHOTOGRAPHER_ID; 

    SELECT FIN_TIME_AVAIL INTO FIN_TIME FROM PH_AV WHERE PHOTOGRAPHER_ID = :NEW.PHOTOGRAPHER_ID; 

    IF ((:NEW.START_TIME_AVAIL >= START_TIME AND :NEW.START_TIME_AVAIL <= FIN_TIME) 
    OR (:NEW.FIN_TIME_AVAIL >= START_TIME AND :NEW.FIN_TIME_AVAIL <= FIN_TIME) 
    OR (:NEW.START_TIME_AVAIL <= START_TIME AND :NEW.FIN_TIME_AVAIL >= FIN_TIME)) 
     THEN 
     DBMS_OUTPUT.PUT_LINE('Cannot be scheduled, photographer unavailable'); 
    ELSE 
    DBMS_OUTPUT.PUT_LINE('PHOTOGRAPHER SUCCESSFULLY SCHEDULED'); 
    END IF; 
    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
      DBMS_OUTPUT.PUT_LINE('NO DATA FOUND'); 
     WHEN OTHERS THEN 
      DBMS_OUTPUT.PUT_LINE('ERROR-' || SQLERRM); 
END; 
/

내가 원하는 기본 논리입니다 : 여기 내 코드입니다. My if 문은 새로운 삽입 된 값이 가능한 모든 예약 된 값과 충돌하는지 확인합니다. 지금이 스크립트를 실행 한 후에는 Script Output에 오류가 있음을 나타내지 않습니다. 그러나 내 메시지 로그는 상당 부분을 주장합니다 (대부분은 (내부 오류) No Throwable Stack Element에서 null입니다.).

이것은 처음으로 트리거를 구현 한 것으로, 선언 된 변수의 Date 데이터 유형을 생각할 수는 있지만 손실이 있습니다. 어떤 제안? 항목의 중복을 방지하기 위해 다음과 요구 사항으로, 나는 다음과 같은 것을 할 것 간단한 구조로

+0

당신의 제목을 편집했습니다 : SQL은 "속편"이라고 쓰여져 있지 않습니다 만, 더 중요한 것은 트리거는 SQL \ * Plus와 거의 관련이 없습니다. 질문은 오라클 트리거에 관한 것입니다. – mathguy

+2

관련 없음, 그러나 : 동일한 테이블에서 4 개의 다른 열을 읽으려면 4 개의 선택이 필요하지 않습니다. 귀하의 경우에는 선택이 전혀 필요 없습니다. ': PHOTOGRAPHER_ID = : NEW.PHOTOGRAPHER_ID'를 사용하여 원하는 정보가 이미 포함되어 있습니다 : –

+0

'설명 PH_AV'를 열 유형을 확인하십시오. 오류 출력의 로그는보고있는 내용을 보여주는 데 도움이됩니다. – slashlos

답변

1

AVAIL 대신 테이블에서 데이터를 검색

CREATE SEQUENCE avail_sq; 

CREATE TABLE avail 
(
    avail_id INTEGER, 
    person_id INTEGER, 
    start_dtm DATE, 
    end_dtm DATE 
); 

CREATE OR REPLACE TRIGGER test_avail_trg 
FOR INSERT OR UPDATE ON avail 
COMPOUND TRIGGER 
    TYPE avail_tt IS TABLE OF avail%ROWTYPE; 

    avail_t avail_tt := avail_tt(); 
    l_cnt INTEGER; 

    BEFORE EACH ROW IS 
    BEGIN 
     avail_t.EXTEND; 
     avail_t(avail_t.COUNT).avail_id := :new.avail_id; 
     avail_t(avail_t.COUNT).person_id := :new.person_id; 
     avail_t(avail_t.COUNT).start_dtm := :new.start_dtm; 
     avail_t(avail_t.COUNT).end_dtm := :new.end_dtm; 
    END BEFORE EACH ROW; 

    AFTER STATEMENT IS 
    BEGIN 
     FOR i IN avail_t.FIRST..avail_t.LAST LOOP 
     SELECT COUNT(*) 
      INTO l_cnt 
      FROM avail a 
      WHERE a.person_id = avail_t(i).person_id 
      AND ((a.start_dtm <= avail_t(i).start_dtm AND a.end_dtm > avail_t(i).start_dtm) OR 
       (a.start_dtm > avail_t(i).start_dtm AND a.start_dtm < avail_t(i).end_dtm)) 
      AND a.avail_id != avail_t(i).avail_id; -- Can't overlap itself 

     IF l_cnt > 0 THEN 
      raise_application_error(-20000, 'Overlap detected'); 
     END IF; 
     END LOOP; 
    END AFTER STATEMENT; 
END; 
/

을, 나는 존재 확인의 이상을 수행하고 . 두 날짜/시간 필터는 어느 지점에서나 겹치는 항목을 확인합니다. 첫 x 째는 새 행과 같거나 이전에 시작한 기존 항목을 점검하고 새 행 시작 후 끝내십시오. 두 번째 행은 새 행 다음에 시작하고 새 행이 끝나기 전에 시작하는 기존 항목을 확인합니다.

이 필드의 업데이트도 허용하기 때문에 COMPOUND TRIGGER을 사용해야합니다. 그러면 각 행에 필요한 데이터를 수집 할 수있을뿐 아니라 명령문이 완료되고 변형이 완료된 후에도 처리 할 수 ​​있습니다.

+2

업데이트에 대해서는 작동하지 않습니다. 업데이트중인 테이블을 선택하면 "변경 중"오류가 발생합니다. – kfinity

+0

당신은 corrent @ kfinity입니다, 나는 원래 질문을 읽을 때'UPDATE'에 대한 요구 사항을 놓쳤습니다. 그 문제를 해결하기 위해 'COMPOUND TRIGGER'로 업데이트되었습니다. –

+0

그래, 방금 돌연변이 문제를 만났어. 기본적으로, 내가 읽는 테이블을 변경하기 위해 트리거를 사용할 수 없습니다. 그러나 나는 그것의 대부분을 이해하지 못하더라도 (오라클과 상호 작용하는 첫 학기) 당신의 생각을 좋아합니다. 나는 이것이 내가 제약으로 다루어야 할 것이라고 생각하고있다.하나를 찾으면 해결책을 게시 할 것입니다. – Breeduss