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 2java


  地址碼含義算法

    身份證前六位是地區代碼,代碼的解釋規則以下:
    abcdef函數

    a:國內區域
    1 華北 三省二市
    2 東北 三省
    3 華東 六省一市
    4 華南 六省
    5 西南 四省一市
    6 西北 五省
    7 臺灣
    8 港澳oop

    b:省代碼
    按照a劃定的分區定義省代碼,
    有直轄市的,直轄市列前,
    其他按離直轄市的距離排序,
    沒有直轄市的,按離北京的遠近排序。編碼

    11-15 京 津 冀 晉 蒙
    21-23 遼 吉 黑
    31-37 滬 蘇 浙 皖 閩 贛 魯
    41-46 豫 鄂 湘 粵 桂 瓊
    50-54 渝 川 貴 雲 藏
    61-65 陝 甘 青 寧 新
    81-82 港 澳code

    cd:城市代碼
    從01開始排,對於直轄市,cd=01表示市轄區,cd=02表示轄縣;
    省的城市代碼從省會開始排,其他依92式機動車號牌的順序排列,
    好比2101=瀋陽 2102=大連……
    只有地級城市有獨立的城市代碼,縣級市沒有。對象

    ef:市轄區、郊區、郊縣、縣級市代碼
    若是ef=00,指代這個城市,不特定區縣;
    對於非直轄市,如ef=01,指代市轄區(任意一個區),02開始指代特定的區。
    其中:
    e=0表明市轄區,
    e=1表明郊區,
    e=2表明郊縣,
    e=8表明縣級市。
    對於直轄市,從01開始就依次排區,沒有市區和郊區的代碼區分。排序

  關於18位身份證號碼尾數是「x」的解釋
   居民身份證的號碼是按照國家的標準編制的,由18位組成:前六位爲行政區劃代碼,第七至第十四位爲出生日期碼,第15至17位爲順序碼,第18位爲校驗碼。做爲尾號的校驗碼,是由號碼編制單位按統一的公式計算出來的,若是某人的尾號是0-9,都不會出現x,但若是尾號是10,那麼就得用x來代替,由於若是用10作尾號,那麼此人的身份證就變成了19位,而19位的號碼違反了國家標準,而且我國的計算機應用系統也不認可19位的身份證號碼。ⅹ是羅馬數字的10,用x來代替10,能夠保證公民的身份證符合國家標準。可是我國的居民身份證在升位後,一些人的尾號變成了x,這部分人在工做生活中,例如去銀行存取錢、去汽車公司租賃汽車或者報名參加考試等等過程當中,每每不被檢驗者理解,認爲是假身份證,這樣的誤會給不少人的生活帶來不便。公安局的同志但願領到x身份證的同志正確理解這個數字的含義,查驗身份證的機關和單位更應該清楚這一點。ci

 

    下面舉例說明校驗碼的計算方法
    15位的身份證編碼首先把出生年擴展爲4位,簡單的就是增長一個19,可是這對於1900年出生的人不使用(這樣的壽星很少了)
    某男性公民身份號碼本體碼爲34052419800101001,首先按照公式(1)計算:
    ∑(ai×wi) mod 11……………………………………(1)
    公式(1)中:
    i----表示號碼字符從右至左包括校驗碼在內的位置序號;
    ai----表示第i位置上的號碼字符值;
    wi----示第i位置上的加權因子,其數值依據公式wi=(2 的 i-1 次冪)(mod 11)計算得出。io

    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;
/

上邊這個函數,通過驗證,發現對於大部分組織機構代碼,都是可使用的,可是對於一小部分,卻會出問題。

SELECT lower('766618250'),jgid_verify(lower('766618250')) FROM dual;

返回值是:錯誤,應該是:7666182511  --這個返回值是錯誤的,由於 7666182511 10位,明顯有問題。

 

下面我提供兩個另外的函數,分別針對10位組織機構代碼和9爲組織機構代碼進行驗證

針對10位組織機構代碼:

--輸入 10位的組織機構代碼(含有-) 格式:12345678-9
--輸出 是否驗證經過,0 未經過,1 經過
create or replace function organizationCode10Verify(organizationCode varchar2)
  return smallint is
  len       number(3); --組織機構代碼長度
  I         int;       
  J         int;
  K         int;
  N         int;
  C         char(1);
  valid     number(1); --是否驗證經過,0 未經過,1 經過
begin
  valid := 0;
  len:= Length(trim(organizationCode));
  
  IF len != 10 then
    return valid;
  END IF;
  IF substr(organizationCode, 9, 1)!='-' then
    return valid;
  END IF;
  I := 1;
  J := 1;
  N := 0;
  while(I <= 8) loop
    K := ASCII(substr(organizationCode, 9-I, 1)) - 48;
    J := trunc(mod((J * 2), 11));
    N := N + J * K;
    I := I + 1;
  END loop;
  N := 11-trunc(mod(N, 11));
  C := substr(organizationCode, 10, 1);
  K := ASCII(C) - 48;
  if N=11 then 
  N:=0;
  END IF;
  IF C='x' OR C='X' THEN 
   K:=10;
  END IF;
  IF K != N then
    return valid;
  END IF;
  valid := 1;
  return valid;
end organizationCode10Verify;
  

 

針對9位組織機構代碼:

 

--輸入 9位的組織機構代碼(不含-) 格式:123456789
--輸出 是否驗證經過,0 未經過,1 經過
create or replace function organizationCode9Verify(organizationCode varchar2)
  return smallint is
  len       number(3); --組織機構代碼長度
  I         int;       
  J         int;
  K         int;
  N         int;
  C         char(1);
  valid     number(1); --是否驗證經過,0 未經過,1 經過
begin
  valid := 0;
  len:= Length(trim(organizationCode));

  IF len != 9 then
    return valid;
  END IF;
  I := 1;
  J := 1;
  N := 0;
  while(I <= 8) loop
    K := ASCII(substr(organizationCode,9-I, 1)) - 48;
    J := trunc(mod((J * 2), 11));
    N := N + J * K;
    I := I + 1;
  END loop;
  N := 11-trunc(mod(N, 11));
  C := substr(organizationCode, 9, 1);
  K := ASCII(C) - 48;
  if N=11 then 
    N:=0;
  END IF;
  IF C='x' OR C='X' THEN 
  K:=10;
  END IF;
  IF K != N then
    return valid;
  END IF;
  valid := 1;
  return valid;
end organizationCode9Verify;
相關文章
相關標籤/搜索