oracle 身份证校验函数的实例代码

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;

总结

以上所述是小编给大家介绍的oracle 身份证校验函数,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

以上是 oracle 身份证校验函数的实例代码 的全部内容, 来源链接: utcz.com/z/347886.html

回到顶部