oracle验证公民身份号码
2009-09-03 16:50
357 查看
首先看一下《公民身份号码》中做了明确的规定:
18位***标准在国家质量技术监督局于1999年7月1日实施的GB11643-1999《公民身份号码》中做了明确的规定。 GB11643-1999《公民身份号码》为GB11643-1989《社会保障号码》的修订版,其中指出将原标准名称"社会保障号码"更名为"公民身份号码",另外GB11643-1999《公民身份号码》从实施之日起代替GB11643-1989。GB11643-1999《公民身份号码》主要内容如下:
一、范围
该标准规定了公民身份号码的编码对象、号码的结构和表现形式,使每个编码对象获得一个唯一的、不变的法定号码。
二、编码对象
公民身份号码的编码对象是具有中华人民共和国国籍的公民。
三、号码的结构和表示形式
1、号码的结构
公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
2、地址码
表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
3、出生日期码
表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
4、顺序码
表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
5、校验码
(1)十七位数字本体码加权求和公式
S = Sum(Ai * Wi), i = 0, ... , 16 ,先对前17位数字的权求和
Ai:表示第i位置上的***号码数字值
Wi:表示第i位置上的加权因子
Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
(2)计算模
Y = mod(S, 11)
(3)通过模得到对应的校验码
Y: 0 1 2 3 4 5 6 7 8 9 10
校验码: 1 0 X 9 8 7 6 5 4 3 2
四、举例如下:
北京市朝阳区: 11010519491231002X
广东省汕头市: 440524188001010014
再看一下***的含义:
'15位***号码含义:
'----------------------------------------
'113343 450321 432(***号:只作假设,可能此号并不存在,请勿对号入座)
'前6位 中间6位 后三位
'地区代码 生日:年月日 奇为男,偶为女
'----------------------------------------
'其中:
'各省市地区国家代码前两位代码是:
'----------------------------------
'北京 11 吉林 22 福建 35 广东 44 云南 53 天津 12 黑龙江 23 江西 36 广西 45 西藏 54 河北 13 上海 31
'山东 37 海南 46 陕西 61 山西 14 江苏 32 河南 41 重庆 50 甘肃 62 内蒙古 15 浙江 33 湖北 42
'四川 51 青海 63 辽宁 21 安徽 34 湖南 43 贵州 52 宁夏 64 新疆 65 台湾 71 香港 81 澳门 82 国外 91
'18位***号:
'---------------------------------------------------
'113343 1945 03 21 432 9(***号:只作假设,可能此号并不存在,请勿对号入座)
'前6位 四位 两位 两位 三位 一位
'地区代码 年份 月份 生日 奇为男,偶为女 检验位
'---------------------------------------------------
'其他不详。
参考资料:http://hsdwf.vicp.net/Content,2005,9,9,101.aspx
###############################################################
15位升18的方法
###############################################################
根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。下面举例说明该计算方法。
15位的***编码首先把出生年扩展为4位,简单的就是增加一个19,但是这对于1900年出生的人不使用(这样的寿星不多了)
某男性公民身份号码本体码为34052419800101001,首先按照公式⑴计算:
∑(ai×Wi)(mod 11)……………………………………(1)
公式(1)中:
i----表示号码字符从由至左包括校验码在内的位置序号;
ai----表示第i位置上的号码字符值;
Wi----示第i位置上的加权因子,其数值依据公式Wi=2(n-1)(mod 11)计算得出。
i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1
Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1
ai×Wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1
根据公式(1)进行计算:
∑(ai×Wi) =(21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189
189 ÷ 11 = 17 + 2/11
∑(ai×Wi)(mod 11) = 2
然后根据计算的结果,从下面的表中查出相应的校验码,其中X表示计算结果为10:
∑(ai×WI)(mod 11) 0 1 2 3 4 5 6 7 8 9 10
校验码字符值ai 1 0 X 9 8 7 6 5 4 3 2
根据上表,查出计算结果为2的校验码为所以该人员的公民身份号码应该为 34052419800101001X。
C#代码:
private string per15To18(string perIDSrc)
{
int iS = 0;
//加权因子常数
int[] iW=new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
//校验码常数
string LastCode="10X98765432";
//新***号
string perIDNew;
perIDNew=perIDSrc.Substring(0,6);
//填在第6位及第7位上填上‘1’,‘9’两个数字
perIDNew += "19";
perIDNew += perIDSrc.Substring(6,9);
//进行加权求和
for( int i=0; i<17; i++)
{
iS += int.Parse(perIDNew.Substring(i,1)) * iW[i];
}
//取模运算,得到模值
int iY = iS%11;
//从LastCode中取得以模为索引号的值,加到***的最后一位,即为新***号。
perIDNew += LastCode.Substring(iY,1);
return perIDNew;
}
源代码如下:
18位***标准在国家质量技术监督局于1999年7月1日实施的GB11643-1999《公民身份号码》中做了明确的规定。 GB11643-1999《公民身份号码》为GB11643-1989《社会保障号码》的修订版,其中指出将原标准名称"社会保障号码"更名为"公民身份号码",另外GB11643-1999《公民身份号码》从实施之日起代替GB11643-1989。GB11643-1999《公民身份号码》主要内容如下:
一、范围
该标准规定了公民身份号码的编码对象、号码的结构和表现形式,使每个编码对象获得一个唯一的、不变的法定号码。
二、编码对象
公民身份号码的编码对象是具有中华人民共和国国籍的公民。
三、号码的结构和表示形式
1、号码的结构
公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
2、地址码
表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
3、出生日期码
表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
4、顺序码
表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
5、校验码
(1)十七位数字本体码加权求和公式
S = Sum(Ai * Wi), i = 0, ... , 16 ,先对前17位数字的权求和
Ai:表示第i位置上的***号码数字值
Wi:表示第i位置上的加权因子
Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
(2)计算模
Y = mod(S, 11)
(3)通过模得到对应的校验码
Y: 0 1 2 3 4 5 6 7 8 9 10
校验码: 1 0 X 9 8 7 6 5 4 3 2
四、举例如下:
北京市朝阳区: 11010519491231002X
广东省汕头市: 440524188001010014
再看一下***的含义:
'15位***号码含义:
'----------------------------------------
'113343 450321 432(***号:只作假设,可能此号并不存在,请勿对号入座)
'前6位 中间6位 后三位
'地区代码 生日:年月日 奇为男,偶为女
'----------------------------------------
'其中:
'各省市地区国家代码前两位代码是:
'----------------------------------
'北京 11 吉林 22 福建 35 广东 44 云南 53 天津 12 黑龙江 23 江西 36 广西 45 西藏 54 河北 13 上海 31
'山东 37 海南 46 陕西 61 山西 14 江苏 32 河南 41 重庆 50 甘肃 62 内蒙古 15 浙江 33 湖北 42
'四川 51 青海 63 辽宁 21 安徽 34 湖南 43 贵州 52 宁夏 64 新疆 65 台湾 71 香港 81 澳门 82 国外 91
'18位***号:
'---------------------------------------------------
'113343 1945 03 21 432 9(***号:只作假设,可能此号并不存在,请勿对号入座)
'前6位 四位 两位 两位 三位 一位
'地区代码 年份 月份 生日 奇为男,偶为女 检验位
'---------------------------------------------------
'其他不详。
参考资料:http://hsdwf.vicp.net/Content,2005,9,9,101.aspx
###############################################################
15位升18的方法
###############################################################
根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。下面举例说明该计算方法。
15位的***编码首先把出生年扩展为4位,简单的就是增加一个19,但是这对于1900年出生的人不使用(这样的寿星不多了)
某男性公民身份号码本体码为34052419800101001,首先按照公式⑴计算:
∑(ai×Wi)(mod 11)……………………………………(1)
公式(1)中:
i----表示号码字符从由至左包括校验码在内的位置序号;
ai----表示第i位置上的号码字符值;
Wi----示第i位置上的加权因子,其数值依据公式Wi=2(n-1)(mod 11)计算得出。
i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1
Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1
ai×Wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1
根据公式(1)进行计算:
∑(ai×Wi) =(21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189
189 ÷ 11 = 17 + 2/11
∑(ai×Wi)(mod 11) = 2
然后根据计算的结果,从下面的表中查出相应的校验码,其中X表示计算结果为10:
∑(ai×WI)(mod 11) 0 1 2 3 4 5 6 7 8 9 10
校验码字符值ai 1 0 X 9 8 7 6 5 4 3 2
根据上表,查出计算结果为2的校验码为所以该人员的公民身份号码应该为 34052419800101001X。
C#代码:
private string per15To18(string perIDSrc)
{
int iS = 0;
//加权因子常数
int[] iW=new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
//校验码常数
string LastCode="10X98765432";
//新***号
string perIDNew;
perIDNew=perIDSrc.Substring(0,6);
//填在第6位及第7位上填上‘1’,‘9’两个数字
perIDNew += "19";
perIDNew += perIDSrc.Substring(6,9);
//进行加权求和
for( int i=0; i<17; i++)
{
iS += int.Parse(perIDNew.Substring(i,1)) * iW[i];
}
//取模运算,得到模值
int iY = iS%11;
//从LastCode中取得以模为索引号的值,加到***的最后一位,即为新***号。
perIDNew += LastCode.Substring(iY,1);
return perIDNew;
}
源代码如下:
CREATE OR REPLACE FUNCTION isidCard(str varchar2) RETURN varchar2 IS areaID char(6) :=substr(str,1,6); birthdayID char(8); sexID char(3); checkID char(1); areaStr varchar(20); birthdayStr1 char(10); birthdayStr2 char(10); birthdayStr3 char(10); birthdayStr4 char(10); sexStr char(3); flag char(2); personInfo varchar2(200); begin if(length(str)!=15 and length(str)!=18)then return '长度不对!'; else select checkarea(areaID) into areaStr from dual; if(areaStr!='NULL') then --地址码是否正确 if(length(str)=15) then --15位 birthdayStr1 :='19'||substr(str,7,6); birthdayStr2 :='20'||substr(str,7,6); select checkbrithday(birthdayStr1) into birthdayStr3 from dual; select checkbrithday(birthdayStr2) into birthdayStr4 from dual; if(birthdayStr3!='NULL' or birthdayStr4!='NULL')then sexID :=substr(str,13,3); select getSex(to_number(sexID)) into sexStr from dual; personInfo :='性别:'||sexStr||' 生日:'||birthdayStr3||'或者'||birthdayStr4||' 地区:'||areaStr; return personInfo; else return '日期错误!'; end if; else --18位 birthdayID :=substr(str,7,8); select checkbrithday(birthdayID) into birthdayStr1 from dual; if(birthdayStr1!='NULL')then select checkCode(str) into flag from dual; if(flag='p')then sexID :=substr(str,15,3); scott.myprint(sexid); select getSex(to_number(sexID)) into sexStr from dual; personInfo :='性别:'||sexStr||' 生日:'||birthdayStr1||' 地区:'||areaStr; return personInfo; else return '校验码错误!'; end if; else return '日期错误!'; end if; end if; else return '地址码错误!'; end if; end if; end; --地址码 CREATE OR REPLACE FUNCTION checkarea(str varchar2) return varchar2 is area varchar2(20); flag number(2); begin select checkarea1(str) into flag from dual; if(flag=1)then select substr(idc,7,(length(idc)-6)) into area from idcardinfo where substr(idc,0,6)=str; return area; else return 'NULL'; end if; end; CREATE OR REPLACE FUNCTION checkarea1(str varchar2) return number is area number(2); begin select count(1) into area from idcardinfo where substr(idc,0,6)=str; return area; end; --出生日期 CREATE OR REPLACE FUNCTION checkbrithday(str varchar2) return varchar2 is birthday varchar2(10); begin select isdate2(str) into birthday from dual; if(birthday!='NULL')then return birthday; else return 'NULL'; end if; end; ---- CREATE OR REPLACE FUNCTION isdate2(str varchar2) RETURN varchar IS v_date date; v_nls varchar2(100) default null; BEGIN SELECT 'NLS_DATE_LANGUAGE='''||value||'''' INTO v_nls FROM v$nls_parameters WHERE parameter='NLS_DATE_LANGUAGE'; v_date := to_date(str, 'yyyy-mm-dd', v_nls); RETURN to_char(v_date,'yyyy-mm-dd'); EXCEPTION WHEN OTHERS THEN /*如果你希望看到报错, 就把下面的注释行打开*/ --raise; RETURN 'NULL'; END; -------------------------------------------------------------------- --性别 CREATE OR REPLACE FUNCTION getSex(str number) RETURN varchar is begin if(str mod 2 =0)then return '女'; else return '男'; end if; end; --校验码 CREATE OR REPLACE FUNCTION checkCode(str varchar2) RETURN varchar is wi char(35) :='7*9*10*5*8*4*2*1*6*3*7*9*10*5*8*4*2'; checkstr char(11) :='10X98765432'; sumcode number(10); checkrel number(2); lastCode char(1); begin sumcode:=to_number(substr(str,1,1))*to_number(substr(wi,1,1))+to_number(substr(str,2,1))*to_number(substr(wi,3,1))+to_number(substr(str,3,1))*to_number(substr(wi,5,2))+to_number(substr(str,4,1))*to_number(substr(wi,8,1))+to_number(substr(str,5,1))*to_number(substr(wi,10,1))+to_number(substr(str,6,1))*to_number(substr(wi,12,1))+to_number(substr(str,7,1))*to_number(substr(wi,14,1))+to_number(substr(str,8,1))*to_number(substr(wi,16,1))+to_number(substr(str,9,1))*to_number(substr(wi,18,1))+to_number(substr(str,10,1))*to_number(substr(wi,20,1))+to_number(substr(str,11,1))*to_number(substr(wi,22,1))+to_number(substr(str,12,1))*to_number(substr(wi,24,1))+to_number(substr(str,13,1))*to_number(substr(wi,26,2))+to_number(substr(str,14,1))*to_number(substr(wi,29,1))+to_number(substr(str,15,1))*to_number(substr(wi,31,1))+to_number(substr(str,16,1))*to_number(substr(wi,33,1))+to_number(substr(str,17,1))*to_number(substr(wi,35,1)); checkrel :=(sumcode mod 11)+1; select substr(checkstr,checkrel,1) into lastCode from dual; if(upper(lastCode)=upper(substr(str,18,1)))then return 'p'; else return 'np'; end if; end; /* 110103198808081226 110103198808121224 11010719880812122x 110101198808121221 110117198808121222 421123198808121223 421125198808121226 42112419880812122x 421123198508121221 */
相关文章推荐
- android ip地址,手机号码,邮箱格式验证
- javascript身份证号码验证-支持新的带X身份证
- php与js方式验证手机号码和邮件地址的合法性,js验证身份证号码
- sql server ,mysql ,oracle 自增长字段设置以及自增长属性的修改验证
- js 手机号码合法性验证代码集合
- oracle 身份验证SQLNET.AUTHENTICATION_SERVICES
- CustomValidator控件 电话和手机号码验证
- Android关于身份证号码的验证
- 正则表达式 手机号码的验证
- Oracle 身份验证方式
- struts2中身份证号码验证
- 正则实现二代身份证号码验证详解
- 手机号码验证正则表达式js
- 验证手机和座机号码的正则表达式
- c#验证18位身份证号码
- php 验证 身份证号码 合法性 兼容 (15位 和 18位身份证号码)
- 身份证号码验证-支持新的带x身份证
- Javasript 身份证号码验证
- TOMCAT下基于表单验证常见问题:(oracle)
- 使用正则表达式验证手机号码