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;