oracle 校验 统一社会信用代码 函数

oracle 校验 统一社会信用代码 函数

前言

oracle 校验 统一社会信用代码 函数,
规范请见《GB 32100-2015 法人和其他组织统一社会信用代码编码规则》及 国家标准第1号修改单,
自2016年4月18日起实施


一、oracle 函数

代码如下(示例):

/*
 1.统一社会信用代码由18位阿拉伯数字或英文大写字母表示(不包括I,O,Z,S,V以防止和阿拉伯字母混淆)
 2.第1位是登记管理部门代码 第2位是机构类别代码,第3-8位是登记管理机关行政区划代码,第9-17是主体标识码(组织机构代码)
 3.第18位是校验码,具体规范请见《GB 32100-2015 法人和其他组织统一社会信用代码编码规则》

 第1位是登记管理部门代码, 国家标准第1号修改单,自2016年4月18日起实施
    机构编制 1
    外交  2
    司法行政  3
    文化  4
    民政  5
    旅游  6
    宗教  7
    工会  8
    工商  9
    中央军委改革和编制办公室  A
    农业  N
    其他  Y
 第2位是机构类别代码
    机构编制
      机关  1
      事业单位  2
      编办直接管理机构编制的群众团体 3
      其他  9
    外交
      外国常驻新闻机构  1
      其他  9
    司法行政
      律师执业机构  1
      公证处 2
      基层法律服务所 3
      司法鉴定机构  4
      仲裁委员会 5
      其他  9
    文化
      外国在华文化中心  1
      其他  9
    民政
      社会团体  1
      民办非企业单位 2
      基金会 3
      其他  9
    旅游
      外国旅游部门常驻代表机构  1
      港澳台地区旅游部门常驻内地(大陆)代表机构 2
      其他  9
    宗教
      宗教活动场所  1
      宗教院校  2
      其他  9
    工会
      基层工会  1
      其他  9
    工商
      企业  1
      个体工商户 2
      农民专业合作社 3
    中央军委改革和编制办公室
      军队事业单位  1
      其他  9
    农业
      组级集体经济组织  1
      村级集体经济组织  2
      乡镇级集体经济组织 3
      其他  9
    其他    1
*/
/*
校验通过返回字符 1,校验未通过及其他错误返回对应错误类型文本
 */
CREATE OR REPLACE FUNCTION FN_UNISCID_CHECK(in_credit_code VARCHAR2)
  RETURN VARCHAR2 IS

  --返回错误信息定义

  --校验成功返回
  success_code               varchar2(4) := '1';
  --统一社会信用代码为空!
  error_code_empty           varchar2(50) := '统一社会信用代码为空!';
  --统一社会信用代码长度错误!
  error_code_length          varchar2(50) := '统一社会信用代码长度错误!';
  --统一社会信用代码省级行政区划代码错误!
  error_code_area            varchar2(50) := '统一社会信用代码省级行政区划代码错误!';
  --统一社会信用代码格式错误
  error_code_format          varchar2(50) := '统一社会信用代码格式错误!';
  --统一社会信用代码校验位错误!
  error_code_check_bit       varchar2(50) := '统一社会信用代码校验位错误!';
  --校验程序异常!
  error_code_other_exception varchar2(50) := '校验程序异常!';

  --其他变量定义

  --统一社会信用代码
  v_credit_code VARCHAR2(100);
  --统一社会信用代码长度
  v_length  NUMBER;
  --统一社会信用代码格式验证正则表达式
  v_regexp_str  VARCHAR2(200);
  --Ci*Wi级数之和
  v_sum NUMBER(10) := 0;
  --校验位对应代码字符值
  v_C18 NUMBER(10);
  --校验位对应代码字符
  v_check_code_char char(1);
  
  /*
    统一社会信用代码字符串中各字符对应的代码字符数值,为在v_Ci字符数组中的位置数-1,
    例如统一社会信用代码91350100M0000100Y4中,
    M对应的字符数值为instr(v_Ci,'M',1,1)-1
    ('0','1','2','3','4','5','6','7','8','9',
     'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','T','U','W','X','Y');
  */
  v_Ci CHAR(31) := '0123456789ABCDEFGHJKLMNPQRTUWXY';
  
  --定义数字型类型数组及变量,与字符位置序号i相对应的加权因子值,Wi=MOD(Power(3, (i - 1)), 31)
  TYPE v_number IS TABLE OF NUMBER;
  v_Wi v_number := v_number(1,3,9,27,19,26,16,17,20,29,25,13,8,24,10,30,28);

  --登记管理机关行政区划代码前两位(省份行政区划代码)
  v_area_code VARCHAR2(200) := '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、去掉'-'、空格、并将小写字母转换为大写字母
  v_credit_code := UPPER(RTRIM(LTRIM(REPLACE(in_credit_code, '-', ''))));

  --2、判断处理后的统一社会信用代码是否为空
  IF (v_credit_code IS NULL) THEN
    BEGIN
      RETURN error_code_empty;
    END;
  END IF;

  --3、判断长度是否为18位
  v_length := LENGTH(v_credit_code);
  IF v_length <> 18 THEN
    RETURN error_code_length;
  END IF;

  --4、判断省级行政区划代码
  IF INSTRB(v_area_code, SUBSTR(v_credit_code, 3, 2) || ',') = 0 THEN
    RETURN error_code_area;
  END IF;

  --5、验证格式:验证统一社会信用代码各位是否在对应字符范围内
  v_regexp_str := '^[1-9ANY][123459][1-8][0-9]{5}[0-9A-Z]{10}$';

  IF NOT REGEXP_LIKE(v_credit_code, v_regexp_str) THEN
    RETURN error_code_format;
  END IF;

  --6、计算校验码

  /*(1)列出代码前17位字符位置序号i相对应的代码字符,以及代码字符对应的代码字符数值Ci
       代码字符:SUBSTR(v_credit_code, i, 1)
       代码字符数值Ci:INSTR(v_Ci,SUBSTR(v_credit_code, i, 1) , 1, 1) - 1
    (2)获取与字符位置序号i相对应的加权因子值Wi
       加权因子值Wi:v_Wi(i)
    (3)计算与字符位置序号i相对应的乘积Ci*Wi
       Ci*Wi:(INSTR(v_Ci, SUBSTR(v_credit_code, i, 1), 1, 1) - 1) * v_Wi(i)
    (4)计算级数之和 
       FOR i IN 1 .. 17 LOOP
          v_sum := v_sum + 
          (INSTR(v_Ci, SUBSTR(v_credit_code, i, 1), 1, 1) - 1) * v_Wi(i);
       END LOOP;
   */
  FOR i IN 1 .. 17 LOOP
    v_sum := v_sum + 
    (INSTR(v_Ci, SUBSTR(v_credit_code, i, 1), 1, 1) - 1) * v_Wi(i);
  END LOOP;
 
 /*
  (5) 计算整数求余函数MOD
      公式: MOD(v_sum, 31)
  (6) 求出校验码字符数值
      v_C18 := 31 - MOD(v_sum, 31);
  */
  v_C18 := 31 - MOD(v_sum, 31);

  /*(7) 找到校验码字符数值对应的代码字符
      当MOD函数值为0(即C18 = 31)时,检验码应用0表示,0的对应值为0
      当MOD函数值为1(即C18 = 30)时,检验码应用符号Y表示,30的对应字符为Y,参考对照表A.1
      SUBSTR(v_Ci, v_C18 + 1, 1)
   */   
   IF v_C18 = 31 then
      v_check_code_char:='0';
   else 
      v_check_code_char:= SUBSTR(v_Ci, v_C18 + 1, 1);
   END IF;

   /*(8)比较入参中第18位校验位与计算出来的校验位是否相同
        统一社会信用代码入参校验位: SUBSTR(v_credit_code,18,1)
   */
   IF (v_check_code_char <> SUBSTR(v_credit_code,18,1)) THEN
        RETURN error_code_check_bit;
   ELSE
        /*校验通过!*/
        RETURN success_code; 
   END IF; 

   /* (9) 函数异常返回提示信息*/
EXCEPTION
  WHEN OTHERS THEN
    RETURN error_code_other_exception;

END FN_UNISCID_CHECK;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值