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;