首页 > 数据库 > 正文

首先说一下身份证的校验规则,如下:

长度必须为15位或者18位;

当长度为15位时,仅允许上传数字;

当长度为18位时,前17位仅允许上传数字,第18位允许数字或“X”。

第18位为校验码,需满足以下计算规则:

a)      对前17位数字本体码加权求和

公式为:S = Sum(Ai * Wi), i = 0, … , 16

其中Ai表示第i位置上的身份证号码数字值,Wi表示第i位置上的加权因子,其各位对应的值依次为:

位数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2

b)     以11对计算结果取模 Y = mod(S, 11)

c)      根据模的值得到对应的校验码,对应关系为:

Y   值

0

1

2

3

4

5

6

7

8

9

10

校验码

1

0

X

9

8

7

6

5

4

3

2

CREATE OR REPLACE FUNCTION F_RULE_CHECKIDCARD(P_IDCARD IN VARCHAR2) RETURN INT IS
  v_regstr    VARCHAR2(2000);                                   --证件校验正则表达式
  v_sum       NUMBER;                                           --对前17位数字本体码加权求和
  v_mod       NUMBER;                                           --以11对计算结果取模 Y = mod(S, 11)
  v_checkcode CHAR(11) := '10X98765432';                        --第18位校验码的取值范围
  v_checkbit  CHAR(1);                                          --第18位校验码
  /*
      --身份证前两位是省份代码
      11       北京市          43       湖南省
      12       天津市          44       广东省
      13       河北省          45       广西壮族自治区
      14       山西省          46       海南省
      15       内蒙古自治区    50       重庆市
      21       辽宁省          51       四川省
      22       吉林省          52       贵州省
      23       黑龙江省        53       云南省
      31       上海市          54       西藏自治区
      32       江苏省          61       陕西省
      33       浙江省          62       甘肃省
      34       安徽省          63       青海省
      35       福建省          64       宁夏回族自治区
      36       江西省          65       新疆维吾尔自治区
      37       山东省          71       台湾省
      41       河南省          81       香港特别行政区
      42       湖北省          82       澳门特别行政区
  */
  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,';
BEGIN
/*
*********************************************身份证号码校验规则*********************************************
1.  长度必须为15位或者18位;
2.  当长度为15位时,仅允许上传数字;
3.  当长度为18位时,前17位仅允许上传数字,第18位允许数字或“X”。
    第18位为校验码,需满足以下计算规则: 
        a)  对前17位数字本体码加权求和 
            公式为:S = Sum(Ai * Wi), i = 0, ... , 16 
            其中Ai表示第i位置上的身份证号码数字值,Wi表示第i位置上的加权因子,其各位对应的值依次为:
            ----------------------------------------------------------------------- 
            位数  1  2  3   4  5  6  7  8  9  10  11  12  13  14  15  16  17
            权    7  9  10  5  8  4  2  1  6  3   7   9   10  5   8   4   2
            -----------------------------------------------------------------------
        b)  以11对计算结果取模 Y = mod(S, 11) 
        c)  根据模的值得到对应的校验码,对应关系为: 
            Y   值   0  1  2  3  4  5  6  7  8  9  10
            校验码   1  0  X  9  8  7	6	 5	4	 3	2
*********************************************身份证号码校验规则*********************************************

--返回是否符合身份证校验规则:0:不符合;1:符合
*/
  CASE LENGTHB(p_idcard)
    WHEN 15 THEN     -- 15位 
      --个性化处理:华海需求,不能是“111111111111111”(连续15个1在以下规则中能够通过)
      IF p_idcard = '111111111111111' THEN  
        RETURN 0;  --0:不符合校验规则
      END IF;

      IF INSTRB(v_areacode, SUBSTR(p_idcard, 1, 2) || ',') = 0 THEN  --前两位不符合省份规则代码
        RETURN 0;  --0:不符合校验规则
      END IF;

      IF MOD(TO_NUMBER(SUBSTRB(p_idcard, 7, 2)) + 1900, 400) = 0 OR
         (MOD(TO_NUMBER(SUBSTRB(p_idcard, 7, 2)) + 1900, 100) <> 0 AND
          MOD(TO_NUMBER(SUBSTRB(p_idcard, 7, 2)) + 1900, 4) = 0) THEN
             -- 规则(闰年):2月包含29号
        v_regstr := '^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$';
      ELSE  -- 规则(平年):2月不包含29号
        v_regstr := '^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$';
      END IF;

      IF REGEXP_LIKE(p_idcard, v_regstr) THEN  --正则校验通过
        RETURN 1; --1:符合校验规则
      ELSE
        RETURN 0; --0:不符合校验规则
      END IF;

    WHEN 18 THEN  -- 18位
      IF INSTRB(v_areacode, SUBSTRB(p_idcard, 1, 2) || ',') = 0 THEN  --前两位不符合省份规则代码
        RETURN 0;  --0:不符合校验规则
      END IF;

      IF MOD(TO_NUMBER(SUBSTRB(p_idcard, 7, 4)), 400) = 0 OR
         (MOD(TO_NUMBER(SUBSTRB(p_idcard, 7, 4)), 100) <> 0 AND
          MOD(TO_NUMBER(SUBSTRB(p_idcard, 7, 4)), 4) = 0) THEN
               -- 规则(闰年):2月包含29号
        v_regstr := '^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9X]$';
      ELSE    -- 规则(平年):2月不包含29号
        v_regstr := '^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9X]$';
      END IF;

      IF REGEXP_LIKE(p_idcard, v_regstr) THEN  --正则校验通过 
        -- 对前17位数字本体码加权求和 
        v_sum      := (TO_NUMBER(SUBSTRB(p_idcard, 1, 1)) +
                      TO_NUMBER(SUBSTRB(p_idcard, 11, 1))) * 7 +
                      (TO_NUMBER(SUBSTRB(p_idcard, 2, 1)) +
                      TO_NUMBER(SUBSTRB(p_idcard, 12, 1))) * 9 +
                      (TO_NUMBER(SUBSTRB(p_idcard, 3, 1)) +
                      TO_NUMBER(SUBSTRB(p_idcard, 13, 1))) * 10 +
                      (TO_NUMBER(SUBSTRB(p_idcard, 4, 1)) +
                      TO_NUMBER(SUBSTRB(p_idcard, 14, 1))) * 5 +
                      (TO_NUMBER(SUBSTRB(p_idcard, 5, 1)) +
                      TO_NUMBER(SUBSTRB(p_idcard, 15, 1))) * 8 +
                      (TO_NUMBER(SUBSTRB(p_idcard, 6, 1)) +
                      TO_NUMBER(SUBSTRB(p_idcard, 16, 1))) * 4 +
                      (TO_NUMBER(SUBSTRB(p_idcard, 7, 1)) +
                      TO_NUMBER(SUBSTRB(p_idcard, 17, 1))) * 2 +
                      TO_NUMBER(SUBSTRB(p_idcard, 8, 1)) * 1 +
                      TO_NUMBER(SUBSTRB(p_idcard, 9, 1)) * 6 +
                      TO_NUMBER(SUBSTRB(p_idcard, 10, 1)) * 3;
        v_mod      := MOD(v_sum, 11);   --以11对计算结果取模 Y = mod(S, 11) 
        v_checkbit := SUBSTRB(v_checkcode, v_mod + 1, 1);  --第18位校验码

        IF v_checkbit = upper(substrb(p_idcard, 18, 1)) THEN  --判断第18位的准确性
          RETURN 1;    --1:符合校验规则(第18位正确)
        ELSE
          RETURN 0;    --0:不符合校验规则(第18位不正确)
        END IF;
      ELSE
        RETURN 0;--0:不符合校验规则(正则校验通过)
      END IF;
    ELSE
      RETURN 0; -- 身份证号码位数不对
  END CASE;
EXCEPTION
  WHEN OTHERS THEN
    RETURN 0;  --异常返回不通过校验
END F_RULE_CHECKIDCARD;

以上内容来自于网络,如有侵权联系即删除。

猜你喜欢
发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论信息