我的身份证上有你的名字(关于居民身份证的身世,你了解多少?你想要知道的都在这里)
中华人民共和国居民身份证是用于证明居住在中华人民共和国境内的公民身份证明文件。自1984年开始颁发第一代居民身份证,至2004年更换第二代居民身份证,居民身份证号码也由原来的15位编码变成18位编码,身份代码是唯一的、终身不变的。在当今高铁出行时你都可以直接刷卡进站,由此可见,居民身份证号码事关你我他,我们都应该好好了解她的身世。
一、居民身份证号码的编码规范
当前,居民身份证号码执行中国国家质量技术监督局于1999年7月1日发布的国家标准:GB11643-1999《公民身份号码》。其中,详细规定了公民身份号码的编码对象、号码结构和表现形式,使得每个编码对象获得一个唯一的、不变的法定号码,简而言之,我们每个人的身份证号码是不会重复的。
(1)编码对象:公民身份号码的编码对象是具有中华人民共和国国籍的公民。
(2)编码结构
15位身份证号码(一代):
第1、2位:省、自治区、直辖市代码
第3、4位:地级市、盟、自治州代码
第5、6位:县、县级市、区代码
第7—12位:出生年月日
第13—15位:顺序号,第15位男为奇数,女为偶数
如:612127760403123代表区县代码为612127、1976年4月3日出生的一名男性。
18位身份证号码(二代):
公民身份号码是特征组合码,由17位数字本体码和1位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
第1、2位:省、自治区、直辖市代码
第3、4位:地级市、盟、自治州代码
第5、6位:县、县级市、区代码
第7—14位:出生年月日
第15—17位:顺序码,第17位男为奇数,女为偶数
第18位:数字校验码
如612127197103020026,代表行政区划代码为612127、1971年3月2日出生的一名女性。
顺序码:是指在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
(3)校验码
校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2中的校验码计算方法计算确定。
基本思路:将身份证号码前17位数分别乘以不同的系数加权求和后再除以11,取余数,通过查看余数与校验码对比表得以计算出校验码为多少。
前17位数字本体码加权求和公式:S = Sum(Ai * Wi),其中i = 0, ... , 16 ,分别对应身份证的前17位数字;
Ai,表示第i位置上的身份证号码数字值;
Wi,表示第i位置上的加权因子,分别是 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2;
Sum求和后,用Y=mod(S, 11)计算出余数。
(注:mod函数为求余函数,其格式为: mod(nExp1,nExp2),即是两个数值表达式作除法运算后的余数)
此时我我们就可以通过下表查看最后一位校验码为多少,以此判定身份证号码真假性。
比如:我们可以验证下居民身份证612127197203221026(此号码仅为虚拟举例)的真伪性。计算如下:
由此,我们就可以看出,计算出的校验码为6,证明上面的身份证号码是真的。
二、居民身份证号码规范性验证SQL语句
以下以福利企业残疾人名单为例予以介绍SQL查询语句。
(1)筛选出残疾人居民身份证号码长度等于15或者长度等于18的记录,生成身份证号码正常表。
select 单位名称,姓名,身份证号码
into 身份证号码正常表
from 福利企业残疾人名单
where (len(身份证号码)=15 or len(身份证号码)=18) and
isdate(
case
when len(身份证号码)=15 then '19'+substring(身份证号码,7,6)
when len(身份证号码)=18 then substring(身份证号码,7,8)
end)=1
注释:本语句不仅要判断身份证号码是否符合15位或18位规定,并且要判断出身份证号码中的出生年月日是否为日期,如出生年月出现19721301就是错误身份证,因为没有第13个月。
(2)筛选出残疾人居民身份证号码长度不等于15或者长度不等于18的记录,生成身份证号码异常表。
select *
into 身份证号码异常表
from dbo.福利企业残疾人名单
where (len(身份证号码)<>15 and len(身份证号码)<>18)
or
isdate(case when len(身份证号码)=15 then '19'+substring(身份证号码,7,6)
when len(身份证号码)=18 then substring(身份证号码,7,8) end)=0
注释:本语句判断身份证号码异常是以长度不为15位且不为18位、或出生年月不是日期为依据。
(3)以身份证号码正常表为基础,用身份证号码进行分组,筛选出身份证号码数量大于1 的记录,生成残疾人重复挂名表。
select 单位名称,姓名,身份证号码
into 残疾人重复挂名表
from 身份证号码正常表
where 身份证号码 in (select 身份证号码
from 身份证号码正常表
group by 身份证号码
having count(姓名)>1)
(4)以身份证号码异常表为基础,按单位名称进行分组,汇总各单位身份证号码异常人数并排序,生成身份证号码异常人数汇总表。
select 单位名称,count(*) 身份证号码异常人数
into 份证号码异常人数汇总表
from 身份证号码异常表
group by 单位名称
(5)在身份证号码正常表中,根据身份证号对比当前日期筛选出满足以下条件的记录并保存:
未满16周岁的;已到退休年龄的(男60岁,女55岁)。
方法一:
select distinct *
from 身份证号码正常表
where ((case when len(身份证号码)=15 then year(getdate())-cast(('19'+substring(身份证号码,7,2))as int)
when len(身份证号码)=18 then year(getdate())-cast(substring(身份证号码,7,4)as int) end)>60 )
and ((case when len(身份证号码)=15 then right(身份证号码,1) when len(身份证号码)=18 then substring(身份证号码,17,1) end) in ('1','3','5','7','9'))
or((case when len(身份证号码)=15 then year(getdate())-cast(('19'+substring(身份证号码,7,2))as int)
when len(身份证号码)=18 then year(getdate())-cast(substring(身份证号码,7,4)as int) end)>55 )
and ((case when len(身份证号码)=15 then right(身份证号码,1) when len(身份证号码)=18 then substring(身份证号码,17,1) end) in ('0','2','4','6','8'))
方法二:
select *
from 身份证号码正常表
where year(getdate())-cast((
case when len(身份证号码)=15 then '19'+substring(身份证号码,7,2)
when len(身份证号码)=18 then substring(身份证号码,7,4) end) as int)<16
union
select * from 身份证号码正常表
where year(getdate())-cast((
case when len(身份证号码)=15 then '19'+substring(身份证号码,7,2)
when len(身份证号码)=18 then substring(身份证号码,7,4) end) as int)>55
and (case when len(身份证号码)=15 then right(身份证号码,1)
when len(身份证号码)=18 then substring(身份证号码,17,1) end) like '[24680]'
union
select * from 身份证号码正常表
where year(getdate())-cast((
case when len(身份证号码)=15 then '19'+substring(身份证号码,7,2)
when len(身份证号码)=18 then substring(身份证号码,7,4) end) as int)>60
and (case when len(身份证号码)=15 then right(身份证号码,1)
when len(身份证号码)=18 then substring(身份证号码,17,1) end) like '[13579]'