Oracle验证身份证号码有效性

废话不多说,直接上代码

create or replace function f_get_idcard_address(p_idcode in varchar2)
/*
   Create By yuxiao 
   2018-04-27
*/
  return varchar is
  v_area varchar2(50);
begin
  select area
    into v_area
    from yuxiao.idcard
   where idcode = substr(p_idcode, 1, 6);
  return v_area;
exception
  when others then
    return null;
end f_get_idcard_address;
create or replace function f_get_idcard_birthday(p_birthday in varchar2)
/*
   Create By yuxiao 
   2018-04-27
*/
  return varchar is
begin
  return to_char(to_date(substr(p_birthday, 7, 8), 'yyyymmdd'),
                 'yyyy"年"mm"月"dd"日"');
exception
  when others then
    return null;
end f_get_idcard_birthday;
create or replace function f_get_idcard_sex(p_sex in varchar2)
/*
   Create By yuxiao 
   2018-04-27
*/
  return varchar is
begin
  return case mod(substr(p_sex, 17, 1), 2) when 1 then '男' when 0 then '女' else null end;
exception
  when others then
    return null;
end f_get_idcard_sex;
create or replace function f_get_idcard_check(p_idcode in varchar2) return varchar is
/*
   Create By yuxiao 
   2018-04-27
*/
  type tiarray is table of integer;
  type tcarray is table of char(1);
  w    tiarray; --数字数组
  a    tcarray; --字符数组
  s    number;
begin
  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');
  s    := 0;
  begin
    for i in 1 .. 17 loop
      s := s + to_number(substr(p_idcode, i, 1)) * w(i);
    end loop;
  exception
    when others then
    return '';
  end;
  s     := s mod 11;
  if a(s + 1) = substr(p_idcode,-1) then
    return 'ok';
  else
    return a(s + 1);
  end if;
exception
  when others then
    return null;
end f_get_idcard_check;
create or replace procedure prc_get_idcard_info(p_idcard in varchar2,
                                                out_str  out varchar2) is
/*
   Create By yuxiao 
   2018-04-27
*/
  v_address  varchar2(50);
  v_birthday varchar2(50);
  v_sex      varchar2(10);
  v_check    varchar2(10);
  v_out_str  varchar2(2000);
  err_cnt    number := 0;
begin
  --格式校验
  if not regexp_like(nvl(p_idcard,'1'),'^\d{17}(\d|X)$') then
    v_out_str := '无效的格式!' || v_check;
    out_str   := out_str || v_out_str;
    err_cnt   := err_cnt + 1;
    return;
  end if;

  --归属地
  v_address := f_get_idcard_address(p_idcard);
  if v_address is null then
    v_out_str := '无效证件号码! 1~6位输入有误';
    out_str   := out_str || v_out_str;
    err_cnt   := err_cnt + 1;
    return;
  end if;

  --出生日
  v_birthday := f_get_idcard_birthday(p_idcard);
  if v_birthday is null then
    v_out_str := '无效证件号码! 7~14位(出生日期)输入有误';
    out_str   := out_str || v_out_str;
    err_cnt   := err_cnt + 1;
    return;
  end if;

  --性别
  v_sex := f_get_idcard_sex(p_idcard);
  if v_sex is null then
    v_out_str := '无效证件号码! 第17位输入有误';
    out_str   := out_str || v_out_str;
    err_cnt   := err_cnt + 1;
    return;
  end if;

  --末位校验码
  v_check := f_get_idcard_check(p_idcard);
  if v_check != 'ok' then
    v_out_str := '无效证件号码! 最末位应该是' || v_check;
    out_str   := out_str || v_out_str;
    err_cnt   := err_cnt + 1;
    return;
  end if;
  
  if err_cnt = 0 then
    v_out_str := v_out_str || '身份证号:' || p_idcard || chr(10);
    v_out_str := v_out_str || '证件地址:' || v_address || chr(10);
    v_out_str := v_out_str || '生    日:' || v_birthday || chr(10);
    v_out_str := v_out_str || '性    别:' || v_sex || chr(10);
    out_str   := v_out_str;
  end if;
exception
  when others then
    v_out_str := '无效证件号码!';
    out_str   := v_out_str;
end prc_get_idcard_info;

运行效果如下:
Oracle验证身份证号码有效性_第1张图片



你可能感兴趣的:(Oracle,Oracle,身份证格式校验,存储过程,Oracle函数)