sql 验证身份证号码

    技术2022-07-10  127

    功能:
    如果输入为15位,如果能转换成相应的18位,则转换并返回18位身份证;
    如果输入为18位,经过校验通过后返回18位身份证
    如果输入的是非法身份证号,返回‘000’
    CREATE OR REPLACE FUNCTION fc_checkid -- ************************************************************************* -- 功能: 如果输入为15位,如果能转换成相应的18位,则转换并返回18位;如果输入为18位,经过校验通过后返回 -- 输出: 判断居民身份证号码的合法性,将合法的15位身份证号码转换为18位 -- 目前所知的居民身份证号码规则为: -- 1、长度为18位(新)或者15位(旧) -- 2、18位的居民身份证最后一位可能是字母'X',其余17位为数字;15位的居民身份证全部由数字组成 -- 3、根据 "ISO7064:1983 MOD11-2" 校验码系统规定的数学关系式计算校验码 -- 输入: 15位或者18位的身份证号码 -- 返回: 18位长度的居民身份证号码 -- ************************************************************************* ( PI_IDIN IN VARCHAR2 -- 身份证号码 ) RETURN VARCHAR2 AS VC_CHARACTER CHAR(1); VC_DAY VARCHAR2(2); VC_MONTH VARCHAR2(2); VC_YEAR VARCHAR2(4); VC_VERIFYBIT CHAR(1); VN_SUM NUMBER; VN_CHECK NUMBER; VC_IDOUT VARCHAR2(18); --输出的18位 VC_ERRCODE VARCHAR2(8); VC_ERRMSG VARCHAR2(320); VE_EXCEPTION EXCEPTION; --创建一个异常 BEGIN VC_IDOUT := PI_IDIN; -- ********************************* -- 总体概要判断(是否为空、长度等等) -- ********************************* IF VC_IDOUT IS NULL THEN VC_ERRCODE := '0100'; VC_ERRMSG := '输入身份证号码是空值'; RAISE VE_EXCEPTION; END IF; IF LENGTHB(VC_IDOUT) <> 15 AND LENGTHB(VC_IDOUT) <> 18 THEN VC_ERRCODE := '0100'; VC_ERRMSG := '居民身份证号码位数不合法'; RAISE VE_EXCEPTION; END IF; -- **************************** -- 对前面17位的非数字字符的合法性判断, 48---57, 一共是10个数字 -- **************************** FOR I IN 1..17 LOOP VC_CHARACTER := SUBSTRB(VC_IDOUT,I,1); IF ASCII(VC_CHARACTER) < 48 OR ASCII(VC_CHARACTER) > 57 THEN VC_ERRCODE := '0100'; VC_ERRMSG := '居民身份证号码第'||I||'位存在非数字字符'; RAISE VE_EXCEPTION; END IF; END LOOP; -- **************************** -- 出生日期的合法性判断 -- **************************** IF LENGTHB(VC_IDOUT) = 15 THEN --如果为15位,这里构造成17位,然后进行校验 VC_IDOUT := SUBSTR(VC_IDOUT,1,6)||'19'||SUBSTR(VC_IDOUT,7,9); END IF; VC_YEAR := SUBSTR(VC_IDOUT,7,4); VC_MONTH := SUBSTR(VC_IDOUT,11,2); VC_DAY := SUBSTR(VC_IDOUT,13,2); IF VC_MONTH > 12 OR VC_DAY > 31 OR (VC_MONTH NOT IN ('01','03','05','07','08','10','12') AND VC_DAY = 31) OR (VC_MONTH = '02' AND VC_DAY > 29) THEN VC_ERRCODE := '0100'; VC_ERRMSG := '居民身份证号码中出生日期不合法'; RAISE VE_EXCEPTION; END IF; -- 闰年的判断 /* 判断闰年的方法是:能被400整除的年是闰年;除能被400整除的年以外,凡是能被4整除, 但不能被100整除的年是闰年。其余年份是平年。 */ IF NOT (MOD(VC_YEAR,400) = 0 OR ( MOD(VC_YEAR,4) = 0 AND MOD(VC_YEAR,100) <> 0)) AND VC_MONTH = '02' AND VC_DAY = 29 THEN VC_ERRCODE := '0100'; VC_ERRMSG := '居民身份证号码中出生日期不合法'; RAISE VE_EXCEPTION; END IF; -- **************************** -- 生成校验位并判断其合法性判断 -- **************************** -- 取校验码 VN_SUM := 0; --求和 FOR I IN 1..17 LOOP VN_SUM := VN_SUM + SUBSTR(VC_IDOUT,I,1) * MOD(POWER(2,((19-I)-1)),11); END LOOP; VN_SUM := MOD(VN_SUM,11);--取模 VN_CHECK := MOD((12 - VN_SUM),11);--得到校验码 --得到校验码 IF VN_CHECK = 10 THEN VC_VERIFYBIT := 'X'; ELSE VC_VERIFYBIT := VN_CHECK; END IF; -- 如果是18位,则判断取校验码合法性 IF SUBSTR(VC_IDOUT,18,1) IS NOT NULL AND UPPER(SUBSTR(VC_IDOUT,18,1)) <> VC_VERIFYBIT THEN VC_ERRCODE := '0100'; VC_ERRMSG := '居民身份证号码中校验位不合法'; RAISE VE_EXCEPTION; END IF; -- 将合法的15位身份证号码转换为18位 VC_IDOUT := SUBSTR(VC_IDOUT,1,17)||VC_VERIFYBIT; -- ******************* -- 成功返回 -- ******************* RETURN VC_IDOUT; EXCEPTION WHEN OTHERS THEN RETURN '000'; END fc_checkid;
    Processed: 0.010, SQL: 9