身份证号码将在今后一段时间内继续存在下去。
另外,项目中往往有着大量的历史数据,我们的一个系统中15位身份证所占比重很大,因此系统必须实现对两套身份证编码的职能处理,并支持另外一种特殊证件类型:军官证/警官证。本文重点讨论15位/18位身份证的处理问题
众所周知,我们现执行的计算机语言实现,需要开发人员自行根据算法设计。网上流传版本不少,不过繁杂而凌乱,且与应用集合描述的不多。现结合项目实践谈谈其处理和用途。
本文主要以ORACLE为例,其他数据库非常类似:*/
--1 号码转换问题
create or replace ID15TO18(p_OldID varchar2) return varchar2 is
type TIArray is table of integer;
type TCArray is table of char(1);
Result varchar2(18);
W TIArray;
A TCArray;
S integer;
begin
if Length(p_OldID) <> 15 OR NOT ISIDCARD(p_OldID) then
--raise_application_error(-20999, '不是旧15位身份证号或者不是身份证号');
Result := p_OldID;
else
W := TIArray(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1);
A := TCArray('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
Result := SubStr(p_OldID, 1, 6) || '19' || SubStr(p_OldID, 7, 9);
S := 0;
begin
for i in 1 .. 17 loop
S := S + to_number(SubStr(Result, i, 1)) * W(i);
end loop;
exception
when others then
return '';
end;
S := S mod 11;
Result := Result || A(s + 1);
end if;
return(Result);
end ID15TO18;
--2 判断是否为create or replace isIDCard(p_IDcard varchar2) return boolean is
IDcardlen integer;
begin
IDcardlen :=Length(p_IDcard);
if (IDcardlen = 18 and IS_NUMBER(SubStr(p_IDcard, 1, IDcardlen-1))
and IS_DATE (substr(p_IDcard,7,8)))
or
(IDcardlen = 15 and IS_NUMBER(SubStr(p_IDcard, 1, IDcardlen))
and IS_DATE ('19' || subsTR(p_IDcard,7,6)))
then
return TRUE;
ELSE
return FALSE;
end if;
end isIDCard;
--3 获取年龄,那获取生日类似,也就不show了
create or replace getAge(p_IDcard varchar2) return integer is
IDcardlen integer;
IDcardyear integer;
begin
IDcardlen :=Length(p_IDcard);
if isidcard(p_IDcard)=1 and IDcardlen = 18 then
IDcardyear := to_number(substr(p_IDcard,7,4));
end if;
if isidcard(p_IDcard)=1 and IDcardlen = 15 then
IDcardyear := to_number('19'||substr(p_IDcard,7,2));
end if;
return to_number(to_char(sysdate,'yyyy'))-IDcardyear;
end getAge;
--3 获取年龄,精确到日
create or replace getAge(p_IDcard varchar2) return integer is
IDcardlen integer;
IDcardyear integer;
begin
IDcardlen :=Length(p_IDcard);
if isidcard(p_IDcard)=1 and IDcardlen = 18 then
IDcardyear := to_number(substr(p_IDcard,7,8));
end if;
if isidcard(p_IDcard)=1 and IDcardlen = 15 then
IDcardyear := to_number('19'||substr(p_IDcard,7,6));
end if;
return to_number(to_char(sysdate,'yyyyMMdd'))-IDcardyear;
end getAge;
--4 获取性别
create or replace getSex(p_IDcard varchar2) return varchar2 is
IDcardlen integer;
begin
IDcardlen :=Length(p_IDcard);
if isidcard(p_IDcard)<>1 then
return null;
end if;
if IDcardlen = 18 and Substr(p_IDcard,17,1) in (1,3,5,7,9) then
return ('男');
end if;
if IDcardlen = 18 and Substr(p_IDcard,17,1) in (2,4,6,8,0)then
return ('女');
end if;
if IDcardlen = 15 and Substr(p_IDcard,15,1) in (1,3,5,7,9) then
return ('男');
end if;
if IDcardlen = 15 and Substr(p_IDcard,15,1) in (2,4,6,8,0)then
return ('女');
end if;
end getSex;
/* (三)总结用途
主要结合某实际项目,说三点:
(1)实现15位/18位身份证号码从15位到18位
这个当然不能轻易机械的升级了,不过如果有重复数据时,判断重复数据,保留最新号码信息绝对是个好办法,如同时存在15位和18位,是否可以留18位就可以了?
(3)智能校验:判断身份证输入,以及关联的性别、*/