트리거에 관한 질문입니다. 3일 동안 고민했는데 모르겠습니다.. 1 6 3,090

by 바나나킥 [PL/SQL] TRIGGER [2014.05.30 18:09:59]


제목 없음.png (10,672Bytes)

CREATE OR REPLACE TRIGGER TRIGGER_TEMP_DAY
    AFTER INSERT ON TEMP
    FOR EACH ROW
DECLARE
    vcGET_DATE         VARCHAR2(8 BYTE);
    vcLOC              VARCHAR2(5 BYTE);
    nMAX               NUMBER(5, 2);
    nMIN               NUMBER(5, 2);
    nCNT               NUMBER(13);
    vcGET_DATE_TEMP    NUMBER;
BEGIN
        SELECT COUNT(*)
        INTO vcGET_DATE_TEMP
        FROM TEMP_DAY
        WHERE LOC = :NEW.LOC
        GROUP BY GET_DATE, LOC;

        SELECT TO_CHAR(GET_TIME, 'YYYYMMDD'), LOC, MAX(TEMP), MIN(TEMP), COUNT(*)
        INTO   vcGET_DATE, vcLOC, nMAX, nMIN, nCNT
        FROM TEMP
        WHERE LOC = :NEW.LOC
        GROUP BY TO_CHAR(GET_TIME, 'YYYYMMDD'), LOC;

    IF vcGET_DATE_TEMP = 0 THEN
        INSERT INTO TEMP_DAY
        (GET_DATE, LOC, MAX, MIN, CNT) VALUES(vcGET_DATE, vcLOC, nMAX, nMIN, nCNT);
    ELSE
        UPDATE TEMP_DAY
        SET    GET_DATE = vcGET_DATE
              ,LOC      = vcLOC
              ,MAX      = nMAX
              ,MIN      = nMIN
              ,CNT      = nCNT
        WHERE LOC = :NEW.LOC;
    END IF;
END;

 

안녕하세요.

TEMP 테이블에 INSERT가 될때에

TEMP_DAY에 INSERT 또는 UPDATE를 시키는 트리거를 작성해보았는데요.

TEMP 테이블의 GET_TIME을 20140530 식의 일자로 변환하여

TEMP_DAY 테이블의 GET_DATE 에 넣어야하고

그렇게 넣은 날짜값과 위치코드 값을 기준으로 삼아서 하루하루의 온도값에 대한 최대값, 최소값, 수신횟수를 구하는 트리거입니다.

TEMP_DAY테이블에 값이 없으면 INSERT를 시키고, 값이 있으면 UPDATE를 시켜야합니다.


TEMP 테이블
수신일시(GET_TIME) -------------------------- 위치코드(LOC)--------------------------온도(TEMP)
2014-05-30 오후 1:30:22                             01                                               23   
2014-05-30 오후 2:30:33                             01                                               6
2014-05-31 오후 3:30:33                             01                                               40
2014-05-31 오후 4:30:22                             01                                               33
2014-05-31 오후 5:22:21                             02                                               22

2014-05-30 오후 2:11:33                             02                                               33

2014-05-30 오후 2:11:34                             02                                               4

-------------------------------------------------------------------------------------------------------------


TEMP_DAY 테이블

수신일자(GET_DATE) ------------위치코드(LOC) ---------최대값(MAX) --------최소값(MIN) ------- 수신횟수(CNT)

20140530                                   01                           23                      6                            2

20140531                                   01                           40                      33                           2

20140530                                   02                           33                      4                            2

20140531                                   02                           22                      22                       1             

 

 

 

이러한 결과값이 나와야하는데 지금 3일째 갈피를 못잡고있습니다...

어디가 잘못된것일까요?

 

 

by spencer [2014.05.30 23:12:19]

line 35의 WHERE 조건을 바꿔보세요.

From:  WHERE LOC = :NEW.LOC;

To: WHERE GET_DATE = vcGET_DATE AND LOC = :NEW.LOC;

 

 


by 바나나킥 [2014.06.02 09:16:22]

답변 감사드립니다!


by 마농 [2014.06.02 08:27:46]
-- temp 테이블에 트리거를 걸때
-- 트리거 안에서 temp 를 참조(Select 등)할 수 없습니다.
-- 따라서, Max , Min, Count 는 temp 에서 직접 구하지 마시고
-- temp_day 에 저장된 값과 비교하여 업데이트 하는 방식으로 구현하세요.
-- 물론 트리거 생성전에 배치작업으로 temp_day 현행화를 시켜 주세요.
CREATE OR REPLACE TRIGGER trigger_temp_day
AFTER INSERT ON temp
FOR EACH ROW
BEGIN
    MERGE INTO temp_day
    USING dual
    ON ( get_date = TO_CHAR(:NEW.get_time, 'yyyymmdd')
    AND loc = :NEW.loc)
    WHEN MATCHED THEN
        UPDATE SET max = GREATEST(max, :NEW.temp)
                 , min = LEAST   (min, :NEW.temp)
                 , cnt = cnt + 1
                 ;
    WHEN NOT MATCHED THEN
        INSERT VALUES
        (TO_CHAR(:NEW.get_time, 'yyyymmdd'), :NEW.loc, :NEW.temp, :NEW.temp, 1)
        ;
END;
/

 


by 바나나킥 [2014.06.02 09:17:26]

답변 감사드립니다!

 

그런데 주석 맨 마지막 줄이 잘 이해가 안갑니다..

배치작업으로 현행화를 시킨다는 것이 잘 이해가 안갑니다..


by 마농 [2014.06.02 09:41:16]
-- 트리거를 적용시키기 전에 최초 한번 temp_day 테이블을 일괄로 갱신시켜 줘야죠.
MERGE INTO temp_day a
USING
(
SELECT TO_CHAR(get_time, 'yyyymmdd') det_date
     , loc
     , MAX(temp) max
     , MIN(temp) min
     , COUNT(*)  cnt
  FROM temp
 GROUP BY TO_CHAR(get_time, 'yyyymmdd'), loc
) b
ON (a.get_date = b.get_date AND a.loc = b.loc)
WHEN MATCHED THEN
    UPDATE SET max = b.max
             , min = b.min
             , cnt = b.cnt
             ;
WHEN NOT MATCHED THEN
    INSERT VALUES
    (b.get_date, b.loc, b.max, b.min, b.cnt)
;

 


by 바나나킥 [2014.06.02 10:48:31]

엄청난 도움이 되었습니다 감사합니다!!

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입