身份證號歸屬地數據庫


信息來源:

https://blog.raymondwu.net/2018/05/11/%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%B7%E5%BD%92%E5%B1%9E%E5%9C%B0%E6%95%B0%E6%8D%AE%E5%BA%93/

 

drop function if EXISTS f_base_check_id_number ;

create function `f_base_check_id_number`(number varchar(18)charset utf8) returns int
/*
-- 作者:黃海
-- 時間:2018-08-21
-- 原理:第一代身份證十五位數升為第二代身份證十八位數的一般規則是:第一步,在原十五位數身份證的第六位數后面插入19 ,這樣身份證號碼即為十七位數;第二步,按照國家規定的統一公式計算出第十八位數,作為校驗碼放在第二代身份證的尾號。
--   校驗碼計算方法:將身份證前十七位數分別乘以不同系數,從第一至十七位的系數分別為7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2,將這十七位數字和系數相乘的結果相加,用加出來的和除以11,看看余數是多少。余數只可能有0、1、2、3、4、5、6、7、8、9、10這十一個數字,其分別對應的最后一位身份證的號碼為1、0、X、9、8、7、6、5、4、3、2,這樣就得出了第二代身份證第十八位數的校驗碼。

-- 測試用例
select f_base_check_id_number('511423198808200077');
*/

BEGIN
-- 區域碼檢查結果
declare v_area_result int;
-- 出生日期年
declare v_year int;
-- 出生日期月
declare v_month int;
-- 出生日期日
declare v_date int;
-- 判斷閏月
declare v_checkdate datetime;
-- 前17位
declare v_17 varchar(17);
-- 臨時變量
declare v_temp int;

-- 前17位的系數
declare v_17_xishu varchar(256);
-- 前17位乘以系數后的和
declare v_sum_17 int;

DECLARE v_i INT ;
declare v_current_xishu int;
declare v_current_number int;
declare v_yushu int;
declare v_jiaoyanma VARCHAR(256);
declare v_last_jiaoyanma varchar(1);
set v_sum_17=0;
-- 系數
set v_17_xishu='7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2';
-- 校驗碼
set v_jiaoyanma='1,0,X,9,8,7,6,5,4,3,2';
set v_i=1;

-- 1、判斷是不是15位或者18位
IF LENGTH(number)<>18  and  LENGTH(number)<>15 then 
  -- -1 代表身份證號長度不是15位,也不是18位
    return -1;
end if;

-- 2、前6位判斷
select count(*) into v_area_result from t_dm_region where `code`=substring(number,1,6);
if v_area_result<>1 then 
  -- -2 代表地區碼錯誤
    return -2;
end if;

-- 3、如果是18位判斷是不是都是數字,如果不都是數字,那前17位是不是數字。
IF LENGTH(number)=18 then 
    SELECT substring(number,1,17) into  v_17;
end if ;

IF LENGTH(number)=15 then 
    SELECT CONCAT(substring(number,1,6),'19',substring(number,7,15)) into  v_17;
end if ;

-- 判斷前面N-1位是不是數字
select v_17  REGEXP '[^0-9.]' into v_temp;

if v_temp=1 then 
    return -3;
    
end if;



-- 4、判斷出生年月日
select substring(number,7,4) into v_year;
select substring(number,11,2) into v_month;
select substring(number,13,2) into v_date;

if not (v_year>=1900 and v_year<=DATE_FORMAT(NOW(), '%Y')) then 
   -- -4代表是出生年份錯誤 
   return -4;
end if;

if not (v_month>=1 and v_month<=12) then 
   -- -5代表是出生月份錯誤 
   return -5;
end if;

if not (v_date>=1 and v_date<=31) then 
   -- -6代表是出生日期錯誤 
   return -6;
end if;

-- 判斷是不是閏年的日期
SELECT DATE_FORMAT(substring(number,7,8), '%Y-%m-%d') into v_checkdate;
if ifnull(v_checkdate,-7)=-7 then 
  return -7;
end if;

-- 5、判斷是不是符合校驗碼規則

-- 對於前17位,都要遍歷一次計算出乘以系數的和
    while v_i<=17 do      
        select CAST(substring(number,v_i,1) as signed) into v_current_number;        
        SELECT CAST(substring_index(substring_index(v_17_xishu,',', v_i), ',',-1) as signed) into v_current_xishu;                
                
        set v_sum_17=v_sum_17+v_current_number*v_current_xishu;                
        set v_i=v_i+1;
    end while;
        
    -- 余數
    set v_yushu=v_sum_17 mod 11;
    SELECT UPPER(substring_index(substring_index(v_jiaoyanma,',', v_yushu+1), ',',-1)) into     v_last_jiaoyanma;
    
   -- 如果是18位,那么最后一位的檢驗碼是不是正確?
IF LENGTH(number)=18 then 
     if  upper(substring(number,18,1))=v_last_jiaoyanma then 
        return 1;
        else
          return -8;
     end if;
end if ;

return 1;    
END

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM