Oracle身份證校驗函式
阿新 • • 發佈:2018-11-07
- Oracle身份證校驗函式
CREATE OR REPLACE FUNCTION FUN_CHECK_SFZ(PRM_SFZ IN VARCHAR2) /*--------------------------------------------------------------------------- *業務環節 :校驗身份證 * 過程名稱 :FUN_CHECK_SFZ * 使用場合 :對身份證號碼進行校驗,通過校驗後返回值為1,也可以返回對應正確的身份證修改205行程式碼 * 其它說明 :返回值組成 ERRCOD+連線符(-)+表名+編號 * ERRCODE-AC01000:身份證號碼為空錯誤 * ERRCODE-AC01001:身份證號碼地區碼非法 * ERRCODE-AC01002:身份證號碼位數非法 * ERRCODE-AC01003:身份證號碼含有非法字元 * ERRCODE-AC01004:身份證出生日期非法 * ERRCODE-AC01005:身份證號碼校驗碼錯誤 * * * 使用要求 : * 作 者 :AnQIang * 完成日期 :2018年11月07日 11:33:24 *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- * 修 改 人 : 修改日期 : *修改描述 : *-------------------------------------------------------------------------*/ RETURN VARCHAR2 IS --變數宣告 S_SFZ VARCHAR2(30) DEFAULT ' '; I_LEN INTEGER DEFAULT 0; I_VALID INTEGER DEFAULT 0; I_FOR INTEGER; S_VALIDCODE CHAR(1); S_BDATE VARCHAR2(8); S_SFZ18 VARCHAR2(18); S_SFZ15 VARCHAR2(15); S_SFZ17 VARCHAR2(17); S_RESULT VARCHAR2(200); V_AREACODE VARCHAR2(2000) := '11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82,91,'; ----[isDate]---- FUNCTION FUN_ISDATE(P_DATE IN VARCHAR2) RETURN BOOLEAN IS V_FLAG BOOLEAN; V_YEAR NUMBER; V_MONTH NUMBER; V_DAY NUMBER; V_ISLEAPYEAR BOOLEAN; BEGIN ----[初始化]---- V_FLAG := TRUE; ----[獲取資訊]---- V_YEAR := TO_NUMBER(SUBSTR(P_DATE, 1, 4)); V_MONTH := TO_NUMBER(SUBSTR(P_DATE, 5, 2)); V_DAY := TO_NUMBER(SUBSTR(P_DATE, 7, 2)); ----[判斷是否為閏年]---- IF (MOD(V_YEAR, 400) = 0) OR (MOD(V_YEAR, 100) <> 0 AND MOD(V_YEAR, 4) = 0) THEN V_ISLEAPYEAR := TRUE; ELSE V_ISLEAPYEAR := FALSE; END IF; ----[判斷月份]---- IF V_MONTH < 1 OR V_MONTH > 12 THEN V_FLAG := FALSE; RETURN V_FLAG; END IF; ----[判斷日期]---- IF V_MONTH IN (1, 3, 5, 7, 8, 10, 12) AND (V_DAY < 1 OR V_DAY > 31) THEN V_FLAG := FALSE; END IF; IF V_MONTH IN (4, 6, 9, 11) AND (V_DAY < 1 OR V_DAY > 30) THEN V_FLAG := FALSE; END IF; IF V_MONTH IN (2) THEN IF (V_ISLEAPYEAR) THEN --[閏年]-- IF (V_DAY < 1 OR V_DAY > 29) THEN V_FLAG := FALSE; END IF; ELSE --[非閏年]-- IF (V_DAY < 1 OR V_DAY > 28) THEN V_FLAG := FALSE; END IF; END IF; END IF; --[返回結果]-- RETURN V_FLAG; END FUN_ISDATE; BEGIN S_SFZ := TRIM(PRM_SFZ); I_LEN := LENGTH(S_SFZ); S_RESULT := '1'; ---------------- IF S_SFZ IS NULL THEN S_RESULT := 'ERRCODE-AC01000:身份證號碼為空錯誤'; GOTO LABEL_END; END IF; ---------------------- ----[地區碼校驗]---- IF INSTRB(V_AREACODE, SUBSTR(S_SFZ, 1, 2) || ',') = 0 THEN S_RESULT := 'ERRCODE-AC01001:身份證號碼地區碼非法'; GOTO LABEL_END; END IF; ----[位數校驗]---- IF I_LEN <> 15 AND I_LEN <> 18 THEN S_RESULT := 'ERRCODE-AC01002:身份證號碼位數非法'; GOTO LABEL_END; END IF; ----[格式化校驗]---- IF TRANSLATE(S_SFZ, CHR(0) || '0123456789xX', CHR(0)) IS NOT NULL OR TRANSLATE(SUBSTR(S_SFZ, 1, 17), CHR(0) || '0123456789', CHR(0)) IS NOT NULL THEN S_RESULT := 'ERRCODE-AC01003:身份證號碼含有非法字元'; GOTO LABEL_END; END IF; ----[出生日期校驗]------- IF I_LEN = 15 THEN IF NOT (FUN_ISDATE('19' || SUBSTR(S_SFZ, 7, 6))) THEN S_RESULT := 'ERRCODE-AC01004:身份證出生日期非法'; GOTO LABEL_END; END IF; END IF; IF I_LEN = 18 THEN IF NOT (FUN_ISDATE(SUBSTR(S_SFZ, 7, 8))) THEN S_RESULT := 'ERRCODE-AC01004:身份證出生日期非法'; GOTO LABEL_END; END IF; END IF; ----[檢查校驗碼]---- IF I_LEN = 18 THEN I_FOR := 17; WHILE I_FOR > 0 LOOP I_VALID := I_VALID + MOD(POWER(2, I_FOR), 11) * TO_NUMBER(SUBSTR(S_SFZ, 18 - I_FOR, 1)); I_FOR := I_FOR - 1; END LOOP; I_VALID := MOD(I_VALID, 11); IF I_VALID = 0 THEN S_VALIDCODE := '1'; ELSIF I_VALID = 1 THEN S_VALIDCODE := '0'; ELSIF I_VALID = 2 THEN S_VALIDCODE := 'X'; ELSIF I_VALID = 3 THEN S_VALIDCODE := '9'; ELSIF I_VALID = 4 THEN S_VALIDCODE := '8'; ELSIF I_VALID = 5 THEN S_VALIDCODE := '7'; ELSIF I_VALID = 6 THEN S_VALIDCODE := '6'; ELSIF I_VALID = 7 THEN S_VALIDCODE := '5'; ELSIF I_VALID = 8 THEN S_VALIDCODE := '4'; ELSIF I_VALID = 9 THEN S_VALIDCODE := '3'; ELSIF I_VALID = 10 THEN S_VALIDCODE := '2'; END IF; IF S_VALIDCODE <> UPPER(SUBSTR(S_SFZ, 18, 1)) THEN S_RESULT := 'ERRCODE-AC01005:身份證號碼校驗碼錯誤'; GOTO LABEL_END; END IF; END IF; --升位 IF I_LEN = 15 THEN S_SFZ17 := SUBSTR(S_SFZ, 1, 6) || '19' || SUBSTR(S_SFZ, 7, 9); I_FOR := 17; WHILE I_FOR > 0 LOOP I_VALID := I_VALID + MOD(POWER(2, I_FOR), 11) * TO_NUMBER(SUBSTR(S_SFZ17, 18 - I_FOR, 1)); I_FOR := I_FOR - 1; END LOOP; I_VALID := MOD(I_VALID, 11); IF I_VALID = 0 THEN S_VALIDCODE := '1'; ELSIF I_VALID = 1 THEN S_VALIDCODE := '0'; ELSIF I_VALID = 2 THEN S_VALIDCODE := 'X'; ELSIF I_VALID = 3 THEN S_VALIDCODE := '9'; ELSIF I_VALID = 4 THEN S_VALIDCODE := '8'; ELSIF I_VALID = 5 THEN S_VALIDCODE := '7'; ELSIF I_VALID = 6 THEN S_VALIDCODE := '6'; ELSIF I_VALID = 7 THEN S_VALIDCODE := '5'; ELSIF I_VALID = 8 THEN S_VALIDCODE := '4'; ELSIF I_VALID = 9 THEN S_VALIDCODE := '3'; ELSIF I_VALID = 10 THEN S_VALIDCODE := '2'; END IF; S_SFZ18 := S_SFZ17 || S_VALIDCODE; ELSE S_SFZ18 := UPPER(S_SFZ); END IF; /*IF S_RESULT = '1' THEN S_RESULT := S_SFZ18; END IF;*/ <<LABEL_END>> RETURN S_RESULT; END FUN_CHECK_SFZ;