Oracle常用函数:IDCARD15TO18() 身份证15位转18位函数

Create   Or   Replace   Function  IDCARD15TO18(CARD  Varchar2 Return   Varchar2   Is
    Type TIARRAY 
Is   Table   Of   Integer ;
    Type TCARRAY 
Is   Table   Of   Char ( 1 );
    RESULTS 
Varchar2 ( 18 );
    W       TIARRAY; 
-- 数字数组
    A       TCARRAY;  -- 字符数组
    S        Integer ;
Begin
    
If  CARD  Is   Null   Then
        
Return   '' ;
    
End   If ;
    
If  LENGTH(CARD)  <>   15   Then
        
Return  CARD;
    
End   If ;
    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 ' );
    RESULTS :
=  SUBSTR(CARD,  1 6 ||   ' 19 '   ||  SUBSTR(CARD,  7 9 );
    S       :
=   0 ;
    
Begin
        
For  I  In   1  ..  17  Loop
            S :
=  S  +  To_Number(SUBSTR(RESULTS, I,  1 ))  *  W(I);
        
End  Loop;
    Exception
        
When  Others  Then
            
Return   '' ;
    
End ;
    S       :
=  S Mod  11 ;
    RESULTS :
=  RESULTS  ||  A(S  +   1 );
    
Return (RESULTS);

End IDCARD15TO18;

----------------------

18位身份证和组织机构代码校验ORACLE函数


18位身份证标准在国家质量技术监督局于1999年7月1日实施的GB11643-1999《公民身份号码》中做了明确规定。
  GB11643-1999《公民身份号码》为GB11643-1989《社会保障号码》的修订版,其中指出将原标准名称“社会保障号码”更名为“公民身份号码”,另外GB11643-1999《公民身份号码》从实施之日起代替GB11643-1989。
  公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码。其含义如下:
  1. 地址码:表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
 2. 出生日期码:表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日分别用4位、2位、2位数字表示,之间不用分隔符。
  3. 顺序码:表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
  校验的计算方式:
  1. 对前17位数字本体码加权求和
  公式为:S = Sum(Ai * Wi), i = 0, ... , 16
  其中Ai表示第i位置上的身份证号码数字值,Wi表示第i位置上的加权因子,其各位对应的值依次为: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
  2. 以11对计算结果取模
  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

15位的身份证号

dddddd yymmdd xx p

18位的身份证号

dddddd yyyymmdd xx p y

其中dddddd为地址码(省地县三级)18位中的和15位中的不完全相同
yyyymmdd yymmdd 为出生年月日
xx顺号类编码
p性别
18位中末尾的y为校验码,在网上可以找到算法

(1)、前两个数字代表省份编码。如:32表示江苏省,34代表安徽省……
(2)、第3、4位上的数字代表市级编码。如:01代表南京市,05代表苏州市……
(3)、第5、6位上的数字代表区或县编码。如:02代表玄武区,11代表浦口区……
(4)、在第7-14位上行政区代码后的数字表示某个人的出生年月。提问:“为什么2月要用02来表示而不用2来表示呢?”(用0来占位可以统一位数。)
(5)、出生年、月、日后面的两个数字表示居住地所在的派出所编码。如阳沟街所在的号码是04。
(6)、老身份证的最后一位,新身份证的倒数第二位数表示性别。提问:哪些数字表示男性?(1、3、5、7、9这样的单数表示男性)。哪些数字表示女性?(0、2、4、6、8这样的双数表示女性)。
(7)、新身份证的最后一位是前面17个数字按一定的公式加减乘除得来的,作为个人信息编码,有的也用X来表示。目的是为了进一步防伪,至于计算公式,只有公安机关内部才知道

本资料从网上多处说明整理而来。
  18位身份证标准在国家质量技术监督局于1999年7月1日实施的GB11643-1999《公民身份号码》中做了明确规定。
  GB11643-1999《公民身份号码》为GB11643-1989《社会保障号码》的修订版,其中指出将原标准名称“社会保障号码”更名为“公民身份号码”,另外GB11643-1999《公民身份号码》从实施之日起代替GB11643-1989。
  公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码。其含义如下:
  1. 地址码:表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
  2. 出生日期码:表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日分别用4位、2位、2位数字表示,之间不用分隔符。
  3. 顺序码:表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
  校验的计算方式:
  1. 对前17位数字本体码加权求和
  公式为:S = Sum(Ai * Wi), i = 0, ... , 16
  其中Ai表示第i位置上的身份证号码数字值,Wi表示第i位置上的加权因子,其各位对应的值依次为: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
  2. 以11对计算结果取模
  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

关于18位身份证号码尾数是“X”的解释
居民身份证的号码是按照国家的标准编制的,由18位组成:前六位为行政区划代码,第七至第十四位为出生日期码,第15至17位为顺序码,第18位为校验码。作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,如果某人的尾号是0-9,都不会出现X,但如果尾号是10,那么就得用X来代替,因为如果用10做尾号,那么此人的身份证就变成了19位,而19位的号码违反了国家标准,并且我国的计算机应用系统也不承认19位的身份证号码。Ⅹ是罗马数字的10,用X来代替10,可以保证公民的身份证符合国家标准。但是我国的居民身份证在升位后,一些人的尾号变成了X,这部分人在工作生活中,例如去银行存取钱、去汽车公司租赁汽车或者报名参加考试等等过程中,往往不被检验者理解,认为是假身份证,这样的误会给很多人的生活带来不便。公安局的同志希望领到X身份证的同志正确理解这个数字的含义,查验身份证的机关和单位更应该清楚这一点。
根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。

★ 地址码含义

身份证前六位是地区代码,代码的解释规则如下:
ABCDEF

A:国内区域
1 华北 三省二市
2 东北 三省
3 华东 六省一市
4 华南 六省
5 西南 四省一市
6 西北 五省
7 台湾
8 港澳

B:省代码
按照A划定的分区定义省代码,
有直辖市的,直辖市列前,
其余按离直辖市的距离排序,
没有直辖市的,按离北京的远近排序。

11-15 京 津 冀 晋 蒙
21-23 辽 吉 黑
31-37 沪 苏 浙 皖 闽 赣 鲁
41-46 豫 鄂 湘 粤 桂 琼
50-54 渝 川 贵 云 藏
61-65 陕 甘 青 宁 新
81-82 港 澳

CD:城市代码
从01开始排,对于直辖市,CD=01表示市辖区,CD=02表示辖县;
省的城市代码从省会开始排,其余依92式机动车号牌的顺序排列,
比如2101=沈阳 2102=大连……
只有地级城市有独立的城市代码,县级市没有。

EF:市辖区、郊区、郊县、县级市代码
如果EF=00,指代这个城市,不特定区县;
对于非直辖市,如EF=01,指代市辖区(任意一个区),02开始指代特定的区。
其中:
E=0代表市辖区,
E=1代表郊区,
E=2代表郊县,
E=8代表县级市。
对于直辖市,从01开始就依次排区,没有市区和郊区的代码区分。

★ 校验码计算方法

下面举例说明校验码的计算方法。

15位的身份证编码首先把出生年扩展为4位,简单的就是增加一个19,但是这对于1900年出生的人不使用(这样的寿星不多了)

某男性公民身份号码本体码为34052419800101001,首先按照公式(1)计算:

∑(ai×Wi) mod 11……………………………………(1)

公式(1)中:
i----表示号码字符从右至左包括校验码在内的位置序号;
ai----表示第i位置上的号码字符值;
Wi----示第i位置上的加权因子,其数值依据公式Wi=(2 的 i-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(男性为大写X;女性为小写x):

∑(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。
程序代码:
CREATE OR REPLACE FUNCTION f_Id_Verify(Pid VARCHAR2) RETURN VARCHAR2 IS
RESULT VARCHAR2(58);
TYPE Char_Tabletype IS TABLE OF VARCHAR2(1) NOT NULL INDEX BY BINARY_INTEGER;
TYPE Num_Tabletype IS TABLE OF NUMBER NOT NULL INDEX BY BINARY_INTEGER;
Tab_a Char_Tabletype;
Tab_w Num_Tabletype;
Tab_i Char_Tabletype;
i NUMBER(2) := 0;
Len NUMBER(2) := Length(Rtrim(Ltrim(Pid)));
Sigma NUMBER(4) := 0;
BEGIN
Tab_i(0) := '1';
Tab_i(1) := '0';
Tab_i(2) := 'X';
Tab_i(3) := '9';
Tab_i(4) := '8';
Tab_i(5) := '7';
Tab_i(6) := '6';
Tab_i(7) := '5';
Tab_i(8) := '4';
Tab_i(9) := '3';
Tab_i(10) := '2';
--Pid := TRIM(Pid);
IF Len = 18 THEN
FOR i IN 1 .. 17 LOOP
Tab_w(i) := MOD(Power(2, ((19 - i) - 1)), 11);
Tab_a(i) := Substr(Pid, i, 1);
Sigma := Sigma + Tab_w(i) * Tab_a(i);
END LOOP;
RESULT := Substr(Pid, 1, 17) || Tab_i(MOD(Sigma, 11));
END IF;
IF RESULT = Pid THEN
RETURN('正确');
ELSE
RETURN('错误,应该是:' || RESULT);
END IF;
EXCEPTION
WHEN OTHERS THEN
BEGIN
RETURN('错误');
Dbms_Output.Put_Line('发生了异常的错误');
END;
END f_Id_Verify;
/




组织机构代码是每一个机关、社会团体、企事业单位在全国范围内唯一的、始终不变的法定代码标识。
最新使用的组织机构代码在1997年颁布实施,由8位数字(或大写拉丁字母)本体代码和1位数字(或大写拉丁字母)校验码组成。本体代码采用系列(即分区段)顺序编码方法。校验码按下列公式计算:
8
C9 = 11 - MOD ( ∑Ci * Wi ,11) … (2)
i=1
其中:MOD —— 表示求余函数;
i —— 表示代码字符从左到右位置序号;
Ci —— 表示第i位置上的代码字符的值,采用附录A“代码字符集”所列字符;
C9 —— 表示校验码;
Wi —— 表示第i位置上的加权因子,其数值如下表:
i 1 2 3 4 5 6 7 8
Wi 3 7 9 10 5 8 4 2
当MOD函数值为1(即 C9 = 10)时,校验码用字母X表示。




  程序代码:
CREATE OR REPLACE FUNCTION Jgid_Verify(Pid VARCHAR2) RETURN VARCHAR2 IS
RESULT VARCHAR2(58);
TYPE Char_Tabletype IS TABLE OF VARCHAR2(1) NOT NULL INDEX BY BINARY_INTEGER;
TYPE Num_Tabletype IS TABLE OF NUMBER NOT NULL INDEX BY BINARY_INTEGER;
Tab_a Char_Tabletype;
Tab_w Num_Tabletype;
Tab_i Char_Tabletype;
i NUMBER(2) := 0;
Len NUMBER(2) := Length(Rtrim(Ltrim(Pid)));
Sigma NUMBER(4) := 0;
BEGIN

IF Len = 9 THEN
-- C9 = 11 - MOD ( ∑Ci * Wi ,11) … (2)
FOR i IN 1 .. 8 LOOP
Tab_w(i) := MOD(Power(2, ((10 - i) - 1)), 11);
--Tab_w(i) := MOD(Power(2, ((10 - i) - 1)), 11); 就是加权算法值
Tab_a(i) := Substr(Pid, i, 1);
Sigma := Sigma + Tab_w(i) * Tab_a(i);
END LOOP;
IF MOD(Sigma, 11) = 1 THEN
RESULT := Substr(Pid, 1, 8) || 'X';
ELSE
RESULT := Substr(Pid, 1, 8) || To_Char(11 - MOD(Sigma, 11));
END IF;
END IF;
IF RESULT = Pid THEN
RETURN('正确');
ELSE
RETURN('错误,应该是:' || RESULT);
END IF;
EXCEPTION
WHEN OTHERS THEN
BEGIN
RETURN('错误');
Dbms_Output.Put_Line('发生了异常的错误');
END;
END Jgid_Verify;
/


CREATE OR REPLACE FUNCTION Jgid_1(Pid VARCHAR2) RETURN VARCHAR2 IS
RESULT VARCHAR2(58);
TYPE Char_Tabletype IS TABLE OF VARCHAR2(1) NOT NULL INDEX BY BINARY_INTEGER;
TYPE Num_Tabletype IS TABLE OF NUMBER NOT NULL INDEX BY BINARY_INTEGER;
--Tab_a Char_Tabletype;
--Tab_w Num_Tabletype;
--Tab_i Char_Tabletype;
i NUMBER(2) := 0;
Len NUMBER(2) := Length(Rtrim(Ltrim(Pid)));
Sigma NUMBER(4) := 0;
type it is table of int;
a it:=it(3,7,9,10,5,8,4,2);

BEGIN

IF Len = 9 THEN
-- C9 = 11 - MOD ( ∑Ci * Wi ,11) … (2)
FOR i IN 1 .. 8 LOOP
--Tab_w(i) := MOD(Power(2, ((10 - i) - 1)), 11);
--Tab_w(i) := MOD(Power(2, ((10 - i) - 1)), 11); 就是加权算法值
--Tab_a(i) := Substr(Pid, i, 1);
--Sigma := Sigma + Tab_w(i) * Tab_a(i);
Sigma := Sigma +Substr(Pid, i, 1)*a(i);
END LOOP;
IF MOD(Sigma, 11) = 1 THEN
RESULT := Substr(Pid, 1, 8) || 'X';
ELSE
RESULT := Substr(Pid, 1, 8) || To_Char(11 - MOD(Sigma, 11));
END IF;
END IF;
IF RESULT = Pid THEN
RETURN('正确');
ELSE
RETURN('错误,应该是:' || RESULT);
END IF;
EXCEPTION
WHEN OTHERS THEN
BEGIN
RETURN('错误');
Dbms_Output.Put_Line('发生了异常的错误');
END;
END Jgid_1;
/


SQL> select count(jgid_1(100000000+level))  from dual connect by level<=100000;

COUNT(JGID_1(100000000+LEVEL))
------------------------------
                        100000

Elapsed: 00:00:04.48

--------------------------------

bool VerifyCode(char code[])  
{  
if(strlen(code)!=9)  
{  
return false;  
}  
//strcpy(code,"HBA90021X");  
int v=0;  
for(int i=0;i<8;i++)  
{  
char c=toupper(code[ i ]);  
if(isdigit(c))  
c-='0';  
else if (isalpha(c))  
c=c-'A'+10;  
else
return false;  
int t=c*((1<<(8-i)) % 11);  
v=v+t;  
}  
v=(11-(v%11))%11;//-------------- 11->0  
if(v<10)  
v=v+'0';  
else
v='X';  
if(v==toupper(code[8])) //------------>'x'-->'X'  
return true;  
else
return false;  

}

--------------------------

import java.io.*;
import java.math.BigDecimal;
import java.lang.Boolean;
import java.lang.Object;

public class testvc
{
    public static void main(String[] args)
    {
int j=0; int i=0;  
char x='A';
x-=10;     
String code;   
for(i=100000001;i<=  100100000;i++)
{
code=Integer.toString(i,10);
if(VerifyCode(code) )
{
j++;
           
}

}
System.out.println(i+":"+j);
for(i=32;i<=65+26;i++)
System.out.println((char)i+";"+i);
    }
static boolean VerifyCode(String code)  
{  
if(code.length()!=9)  
{  
return false;  
}  
//strcpy(code,"HBA90021X";  
int v=0;  
for(int i=0;i<8;i++)  
{  
char c=code.charAt( i );  
if(c>='0' && c<='9')  
c-='0';  
else if (c>='A' && c<='Z')  
c-='7';//'A'+10;  
else
return false;  
int t=c*((1<<(8-i)) % 11);  
v=v+t;  
}  
v=(11-(v%11))%11;//-------------- 11->0  
if(v<10)  
v=v+'0';  
else
v='X';  
C:\__>Cracleora92jdkinjavac testvc.java

C:\__>java testvc
100100001:9091
;32
!;33
";34
#;35
$;36
%;37
&;38
';39
(;40
);41
*;42
+;43
,;44
-;45
.;46
/;47
0;48
1;49
2;50
3;51
4;52
5;53
6;54
7;55
8;56
9;57
:;58
;;59
<;60
=;61
>;62
?;63
@;64
A;65
B;66
C;67
D;68
E;69
F;70
G;71
H;72
I;73
J;74
K;75
L;76
M;77
N;78
O;79
P;80
Q;81
R;82
S;83
T;84
U;85
V;86
W;87
X;88
Y;89
Z;90
[;91

①②⑧

-----------------------------

身份证校验码算法
   身份证校验码产生方法:
∑(ai×Wi)(mod 11)

i:  表示号码字符从由至左包括校验码在内的位置序号;

ai   表示第i位置上的号码字符值;

Wi  第i位置上的加权因子,其数值Wi=mod(power(2,(n-1)),11)

i  18 17 16 15 14 13 12 11 10 9 8 7  6 5  4 3 2 1
Wi 7 9  10   5 8     4   2   1   6 3 7 9 10 5 8 4 2 1

相应的校验码:
∑(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

CREATE OR REPLACE FUNCTION f_id_verify(pid VARCHAR2) RETURN VARCHAR2 IS
  RESULT VARCHAR2(18);
  TYPE char_tabletype IS TABLE OF VARCHAR2(1) NOT NULL INDEX BY BINARY_INTEGER;
  TYPE num_tabletype IS TABLE OF NUMBER NOT NULL INDEX BY BINARY_INTEGER;
  tab_a char_tabletype;
  tab_w num_tabletype;
  tab_i char_tabletype;
  i     NUMBER(2) := 0;
  len   NUMBER(2) := length(rtrim(ltrim(pid)));
  sigma NUMBER(4) := 0;
BEGIN
  tab_i(0) := '1';
  tab_i(1) := '0';
  tab_i(2) := 'x';
  tab_i(3) := '9';
  tab_i(4) := '8';
  tab_i(5) := '7';
  tab_i(6) := '6';
  tab_i(7) := '5';
  tab_i(8) := '4';
  tab_i(9) := '3';
  tab_i(10) := '2';
  IF len = 18 THEN
    FOR i IN 1 .. 17
    LOOP
      tab_w(i) := MOD(power(2, ((19 - i) - 1)), 11);
      tab_a(i) := substr(pid, i, 1);
      sigma := sigma + tab_w(i) * tab_a(i);
    END LOOP;
    RESULT := substr(pid, 1, 17) || tab_i(MOD(sigma, 11));
  END IF;
  RETURN(RESULT);
END f_id_verify;
/

----------------------------------

最初由 cyr1974 发布
[B]讲讲Wi=mod(power(2,(n-1)),11)的意思? [/B]



num_list(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
    char (i)    mod(2 exp(i),11)

for example    2=2  mod(2,11)=2,
                 2*2=4  mod(4,11)=4,
                  .
                  .
                  .
                  .
                 2exp(6)=64 mod(64,11)=9




你可能感兴趣的:(Oracle)