1、正则表达式写法:
create or replace function func_checkidcard (p_idcard in varchar2) return int
is
v_regstr varchar2 (2000);
v_sum number;
v_mod number;
v_checkcode char (11) := '10x98765432';
v_checkbit char (1);
v_areacode varchar2 (2000) := '11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82,91,';
begin
case lengthb (p_idcard)
when 15
then -- 15位
if instrb (v_areacode, substr (p_idcard, 1, 2) || ',') = 0 then
return 0;
end if;
if mod (to_number (substrb (p_idcard, 7, 2)) + 1900, 400) = 0
or
(
mod (to_number (substrb (p_idcard, 7, 2)) + 1900, 100) <> 0
and
mod (to_number (substrb (p_idcard, 7, 2)) + 1900, 4) = 0
)
then -- 闰年
v_regstr :=
'^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$';
else
v_regstr :=
'^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$';
end if;
if regexp_like (p_idcard, v_regstr) then
return 1;
else
return 0;
end if;
when 18
then -- 18位
if instrb (v_areacode, substrb (p_idcard, 1, 2) || ',') = 0 then
return 0;
end if;
if mod (to_number (substrb (p_idcard, 7, 4)), 400) = 0
or
(
mod (to_number (substrb (p_idcard, 7, 4)), 100) <> 0
and
mod (to_number (substrb (p_idcard, 7, 4)), 4) = 0
)
then -- 闰年
v_regstr :=
'^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9xx]$';
else
v_regstr :=
'^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9xx]$';
end if;
if regexp_like (p_idcard, v_regstr) then
v_sum :=
( to_number (substrb (p_idcard, 1, 1))
+ to_number (substrb (p_idcard, 11, 1))
)
* 7
+ ( to_number (substrb (p_idcard, 2, 1))
+ to_number (substrb (p_idcard, 12, 1))
)
* 9
+ ( to_number (substrb (p_idcard, 3, 1))
+ to_number (substrb (p_idcard, 13, 1))
)
* 10
+ ( to_number (substrb (p_idcard, 4, 1))
+ to_number (substrb (p_idcard, 14, 1))
)
* 5
+ ( to_number (substrb (p_idcard, 5, 1))
+ to_number (substrb (p_idcard, 15, 1))
)
* 8
+ ( to_number (substrb (p_idcard, 6, 1))
+ to_number (substrb (p_idcard, 16, 1))
)
* 4
+ ( to_number (substrb (p_idcard, 7, 1))
+ to_number (substrb (p_idcard, 17, 1))
)
* 2
+ to_number (substrb (p_idcard, 8, 1)) * 1
+ to_number (substrb (p_idcard, 9, 1)) * 6
+ to_number (substrb (p_idcard, 10, 1)) * 3;
v_mod := mod (v_sum, 11);
v_checkbit := substrb (v_checkcode, v_mod + 1, 1);
if v_checkbit = upper(substrb(p_idcard,18,1)) then
return 1;
else
return 0;
end if;
else
return 0;
end if;
else
return 0; -- 身份证号码位数不对
end case;
exception
when others
then
return 0;
end fn_checkidcard;
/
show err;
2、非正则表达式写法
create or replace function func_checkidcard (p_idcard in varchar2) return number
is
v_sum number;
v_mod number;
v_length number;
v_date varchar2(10);
v_isdate boolean;
v_isnumber boolean;
v_isnumber_17 boolean;
v_checkbit char (1);
v_checkcode char (11) := '10x98765432';
v_areacode varchar2 (2000) := '11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82,91,';
--[isnumber]--
function isnumber (p_string in varchar2) return boolean
is
i number;
k number;
flag boolean;
v_length number;
begin
/*
算法:
通过ascii码判断是否数字,介于[48, 57]之间。
select ascii('0'),ascii('1'),ascii('2'),ascii('3'),ascii('4'),ascii('5'),ascii('6'),ascii('7'),ascii('8'),ascii('9') from dual;
*/
flag := true;
select length(p_string) into v_length from dual;
for i in 1..v_length loop
k := ascii(substr(p_string,i,1));
if k < 48 or k > 57 then
flag := false;
exit;
end if;
end loop;
return flag;
end isnumber;
--[isdate]--
function isdate (p_date in varchar2) return boolean
is
v_flag boolean;
v_year number;
v_month number;
v_day number;
v_isleapyear boolean;
begin
--[初始化]--
v_flag := true;
--[获取信息]--
v_year := to_number(substr(p_date,1,4));
v_month := to_number(substr(p_date,5,2));
v_day := to_number(substr(p_date,7,2));
--[判断是否为闰年]--
if (mod(v_year,400) = 0) or (mod(v_year,100) <> 0 and mod(v_year,4) = 0) then
v_isleapyear := true;
else
v_isleapyear := false;
end if;
--[判断月份]--
if v_month < 1 or v_month > 12 then
v_flag := false;
return v_flag;
end if;
--[判断日期]--
if v_month in (1,3,5,7,8,10,12) and (v_day < 1 or v_day > 31) then
v_flag := false;
end if;
if v_month in (4,6,9,11) and (v_day < 1 or v_day > 30) then
v_flag := false;
end if;
if v_month in (2) then
if (v_isleapyear) then
--[闰年]--
if (v_day < 1 or v_day > 29) then
v_flag := false;
end if;
else
--[非闰年]--
if (v_day < 1 or v_day > 28) then
v_flag := false;
end if;
end if;
end if;
--[返回结果]--
return v_flag;
end isdate;
begin
/*
返回值说明:
-1 身份证号码位数不对
-2 身份证号码出生日期超出范围
-3 身份证号码含有非法字符
-4 身份证号码校验码错误
-5 身份证号码地区码非法
身份证号码通过校验
*/
--[长度校验]--
if p_idcard is null then
return -1;
end if ;
select lengthb(p_idcard) into v_length from dual;
if v_length not in (15,18) then
return -1;
end if;
--[区位码校验]--
if instrb(v_areacode, substr(p_idcard, 1, 2)||',') = 0 then
return -5;
end if;
--[格式化校验]--
if v_length = 15 then
v_isnumber := isnumber (p_idcard);
if not (v_isnumber) then
return -3;
end if;
elsif v_length = 18 then
v_isnumber := isnumber (p_idcard);
v_isnumber_17 := isnumber (substr(p_idcard,1,17));
if not ((v_isnumber) or (v_isnumber_17 and upper(substr(p_idcard,18,1)) = 'x')) then
return -3;
end if;
end if;
--[出生日期校验]--
if v_length = 15 then
select '19'||substr(p_idcard,7,6) into v_date from dual;
elsif v_length = 18 then
select substr(p_idcard,7,8) into v_date from dual;
end if;
v_isdate := isdate (v_date);
if not (v_isdate) then
return -2;
end if;
--[校验码校验]--
if v_length = 18 then
v_sum :=
( to_number (substrb (p_idcard, 1, 1))
+ to_number (substrb (p_idcard, 11, 1))
)
* 7
+ ( to_number (substrb (p_idcard, 2, 1))
+ to_number (substrb (p_idcard, 12, 1))
)
* 9
+ ( to_number (substrb (p_idcard, 3, 1))
+ to_number (substrb (p_idcard, 13, 1))
)
* 10
+ ( to_number (substrb (p_idcard, 4, 1))
+ to_number (substrb (p_idcard, 14, 1))
)
* 5
+ ( to_number (substrb (p_idcard, 5, 1))
+ to_number (substrb (p_idcard, 15, 1))
)
* 8
+ ( to_number (substrb (p_idcard, 6, 1))
+ to_number (substrb (p_idcard, 16, 1))
)
* 4
+ ( to_number (substrb (p_idcard, 7, 1))
+ to_number (substrb (p_idcard, 17, 1))
)
* 2
+ to_number (substrb (p_idcard, 8, 1)) * 1
+ to_number (substrb (p_idcard, 9, 1)) * 6
+ to_number (substrb (p_idcard, 10, 1)) * 3;
v_mod := mod (v_sum, 11);
v_checkbit := substrb (v_checkcode, v_mod + 1, 1);
if v_checkbit = upper(substrb(p_idcard,18,1)) then
return 1;
else
return -4;
end if;
else
return 1;
end if;
end func_checkidcard;
/
show err;
总结
以上所述是www.887551.com给大家介绍的oracle 身份证校验函数,希望对大家有所帮助