zoukankan      html  css  js  c++  java
  • ORACLE对身份证号码处理相关的SQL【收藏】

    /*ORACLE对身份证号码处理相关的SQL汇总 
    
    身份证号码算法及应用场景:
    
             工作实践总结,与大家分享快乐,并请高人批评指正,努力改进:
    
              目前我国大量存在着正在有效期的15位身份证,虽然国家在推行二代身份证,但尚未发现强行要求全国人民更换未到期的15位身份证的官方声明或公告。
              扯远了:),总之合法的15位身份证号码将在今后一段时间内继续存在下去。
    
             另外,项目中往往有着大量的历史数据,我们的一个系统中15位身份证所占比重很大,因此系统必须实现对两套身份证编码的职能处理,并支持另外一种特殊证件类型:军官证/警官证。本文重点讨论15位/18位身份证的处理问题
    
             众所周知,我们现执行的身份证号码编码由公安部具体落实编码规则,有15位/18位两种,公安部以数学语言描述的方式公开了身份证编码规则和位码含义,但具体到计算机语言实现,需要开发人员自行根据算法设计。网上流传版本不少,不过繁杂而凌乱,且与应用集合描述的不多。现结合项目实践谈谈其处理和用途。
             本文主要以oracle的SQL为例子,其他语言大家可以自行转换,道理都是一样的。
    
    这里以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位号码登录,应提示相关信息,辅助完成系统登录。
         反之,提示用户号码输入不正确。
    
    
    (2)自动升级库中的身份证号码从15位到18位
        
         这个当然不能轻易机械的升级了,不过如果有重复数据时,判断重复数据,保留最新号码信息绝对是个好办法,如同时存在15位和18位,是否可以留18位就可以了?
    
    (3)智能校验:判断身份证输入,以及关联的性别、出生年月等是否正确
      
         按公安部门发布的号码规则校验,当然是有效和有用的:)*/
     
  • 相关阅读:
    利用游标循环插入数据
    局部临时表
    表值函数
    SQL2000自动备份压缩删除数据库
    insert select、select into 的用法
    判断每个页面是否登以及捕捉页面异常录解决方案
    合并查询结果
    字符串分隔(转自别处)
    生成行号
    C#计算字符串中子串出现次数的另类方法
  • 原文地址:https://www.cnblogs.com/xgxhellboy/p/3120470.html
Copyright © 2011-2022 走看看