본문 바로가기
Dev/SQL

[Oracle] 날짜 유효성 검사 함수

by dev_jsk 2020. 11. 3.
728x90
반응형

날짜 유효성 검사

날짜 데이터의 유효성을 확인하기 위한 함수로 데이터 형식에 따라 해당 형식에 맞는지 검사한다.

 

함수 인수

날짜값, 데이터 형식 (D - YYYYMMDD, T - YYYYMMDDHH24MISS)

 

구성

create or replace FUNCTION "FN_ISERR_DATE" (IN_STR IN VARCHAR2, IN_TYPE IN VARCHAR2)
    RETURN VARCHAR2
/****************************************************************************
/* 함수명 : FN_ISERR_DATE
/*
/* 설  명 : 날짜 유효성 검증
/*
/* 인  수 : 날짜값, 년월일(D) or 년월일시분초(T) 타입값
/*
/* 참고 사항 : 정규식 이용, 유효하지 않은 값은 빈값으로 리턴, 문자입력 시에도 빈값으로 리턴
/****************************************************************************/
IS
    V_RETURN    VARCHAR2 (512);     -- 결과값
    V_STR       VARCHAR2 (512);     -- 입력값(날짜)
    V_YEAR      VARCHAR2 (4);       -- 입력값 내 년도
    V_LEAF      VARCHAR2 (1);       -- 입력값 윤년 여부
    V_REGEXP    VARCHAR2 (512);     -- 윤년 여부에 따른 정규식
    V_TYPE      VARCHAR2 (1);       -- 년월일 or 년월일시분초 타입
BEGIN
    -- 입력값 공백제거
    V_STR := TRIM(IN_STR);
    -- 년월일 or 년월일시분초 타입
    V_TYPE := IN_TYPE;
    
    IF      -- 빈값
        V_STR IS NULL OR V_STR = ''
    THEN
        V_RETURN := '';
    ELSIF   -- 숫자이외 값 확인
        REGEXP_INSTR(V_STR, '[^0-9]') != 0
    THEN
        V_RETURN := '';
    -- YYYYMMDD
    ELSIF
        V_TYPE = 'D'
    THEN
        IF      -- 자리수(년월일)
            LENGTH(V_STR) != 8
        THEN
            V_RETURN := '';
        ELSE   -- 날짜 및 윤년계산
            V_YEAR := SUBSTR(V_STR, 0, 4);
            CASE WHEN
                (MOD(V_YEAR, 4) = 0 AND MOD(V_YEAR, 100) != 0)
                OR
                (MOD(V_YEAR, 400) = 0)
            THEN
                V_LEAF := 'Y';
            ELSE
                V_LEAF := 'N';
            END CASE;
            
            IF
                V_LEAF = 'Y'
            THEN
                V_REGEXP := '^[0-9]{4}(((0[13578]|(10|12))(0[1-9]|[1-2][0-9]|3[0-1]))|(02(0[1-9]|[1-2][0-9]))|((0[469]|11)(0[1-9]|[1-2][0-9]|30)))$';
            ELSE
                V_REGEXP := '^[0-9]{4}(((0[13578]|(10|12))(0[1-9]|[1-2][0-9]|3[0-1]))|(02(0[1-9]|[1-2][0-8]))|((0[469]|11)(0[1-9]|[1-2][0-9]|30)))$';
            END IF;
            
            CASE WHEN
                NOT REGEXP_LIKE(V_STR, V_REGEXP)
            THEN
                V_RETURN := '';
            ELSE
                V_RETURN := V_STR;
            END CASE;
        END IF;
    -- YYYYMMDDHH24MISS
    ELSIF
        V_TYPE = 'T'
    THEN
        IF      -- 자리수(년월일시분초)
            LENGTH(V_STR) != 14
        THEN
            V_RETURN := '';
        ELSE   -- 날짜 및 윤년계산
            V_YEAR := SUBSTR(V_STR, 0, 4);
            CASE WHEN
                (MOD(V_YEAR, 4) = 0 AND MOD(V_YEAR, 100) != 0)
                OR
                (MOD(V_YEAR, 400) = 0)
            THEN
                V_LEAF := 'Y';
            ELSE
                V_LEAF := 'N';
            END CASE;
            
            IF
                V_LEAF = 'Y'
            THEN
                V_REGEXP := '^[0-9]{4}(((0[13578]|(10|12))(0[1-9]|[1-2][0-9]|3[0-1]))|(02(0[1-9]|[1-2][0-9]))|((0[469]|11)(0[1-9]|[1-2][0-9]|30)))(([0-1][0-9]|2[0-4])([0-5][0-9])([0-5][0-9]))$';
            ELSE
                V_REGEXP := '^[0-9]{4}(((0[13578]|(10|12))(0[1-9]|[1-2][0-9]|3[0-1]))|(02(0[1-9]|[1-2][0-8]))|((0[469]|11)(0[1-9]|[1-2][0-9]|30)))(([0-1][0-9]|2[0-4])([0-5][0-9])([0-5][0-9]))$';
            END IF;
            
            CASE WHEN
                NOT REGEXP_LIKE(V_STR, V_REGEXP)
            THEN
                V_RETURN := '';
            ELSE
                V_RETURN := V_STR;
            END CASE;
        END IF;
    END IF;

    RETURN V_RETURN;
EXCEPTION   -- 오류
    WHEN OTHERS
    THEN
        V_RETURN := 'ERR';
        RETURN V_RETURN;
END FN_ISERR_DATE;
728x90
반응형

댓글