zoukankan      html  css  js  c++  java
  • oracle 身份证校验函数

    1、正则表达式写法:

      1 CREATE OR REPLACE FUNCTION fn_checkidcard (p_idcard IN VARCHAR2) RETURN INT
    2 IS
    3 v_regstr VARCHAR2 (2000);
    4 v_sum NUMBER;
    5 v_mod NUMBER;
    6 v_checkcode CHAR (11) := '10X98765432';
    7 v_checkbit CHAR (1);
    8 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,';
    9 BEGIN
    10 CASE LENGTHB (p_idcard)
    11 WHEN 15
    12 THEN -- 15位
    13 IF INSTRB (v_areacode, SUBSTR (p_idcard, 1, 2) || ',') = 0 THEN
    14 RETURN 0;
    15 END IF;
    16
    17 IF MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 2)) + 1900, 400) = 0
    18 OR
    19 (
    20 MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 2)) + 1900, 100) <> 0
    21 AND
    22 MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 2)) + 1900, 4) = 0
    23 )
    24 THEN -- 闰年
    25 v_regstr :=
    26 '^[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}$';
    27 ELSE
    28 v_regstr :=
    29 '^[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}$';
    30 END IF;
    31
    32 IF REGEXP_LIKE (p_idcard, v_regstr) THEN
    33 RETURN 1;
    34 ELSE
    35 RETURN 0;
    36 END IF;
    37 WHEN 18
    38 THEN -- 18位
    39 IF INSTRB (v_areacode, SUBSTRB (p_idcard, 1, 2) || ',') = 0 THEN
    40 RETURN 0;
    41 END IF;
    42
    43 IF MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 4)), 400) = 0
    44 OR
    45 (
    46 MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 4)), 100) <> 0
    47 AND
    48 MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 4)), 4) = 0
    49 )
    50 THEN -- 闰年
    51 v_regstr :=
    52 '^[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]$';
    53 ELSE
    54 v_regstr :=
    55 '^[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]$';
    56 END IF;
    57
    58 IF REGEXP_LIKE (p_idcard, v_regstr) THEN
    59 v_sum :=
    60 ( TO_NUMBER (SUBSTRB (p_idcard, 1, 1))
    61 + TO_NUMBER (SUBSTRB (p_idcard, 11, 1))
    62 )
    63 * 7
    64 + ( TO_NUMBER (SUBSTRB (p_idcard, 2, 1))
    65 + TO_NUMBER (SUBSTRB (p_idcard, 12, 1))
    66 )
    67 * 9
    68 + ( TO_NUMBER (SUBSTRB (p_idcard, 3, 1))
    69 + TO_NUMBER (SUBSTRB (p_idcard, 13, 1))
    70 )
    71 * 10
    72 + ( TO_NUMBER (SUBSTRB (p_idcard, 4, 1))
    73 + TO_NUMBER (SUBSTRB (p_idcard, 14, 1))
    74 )
    75 * 5
    76 + ( TO_NUMBER (SUBSTRB (p_idcard, 5, 1))
    77 + TO_NUMBER (SUBSTRB (p_idcard, 15, 1))
    78 )
    79 * 8
    80 + ( TO_NUMBER (SUBSTRB (p_idcard, 6, 1))
    81 + TO_NUMBER (SUBSTRB (p_idcard, 16, 1))
    82 )
    83 * 4
    84 + ( TO_NUMBER (SUBSTRB (p_idcard, 7, 1))
    85 + TO_NUMBER (SUBSTRB (p_idcard, 17, 1))
    86 )
    87 * 2
    88 + TO_NUMBER (SUBSTRB (p_idcard, 8, 1)) * 1
    89 + TO_NUMBER (SUBSTRB (p_idcard, 9, 1)) * 6
    90 + TO_NUMBER (SUBSTRB (p_idcard, 10, 1)) * 3;
    91 v_mod := MOD (v_sum, 11);
    92 v_checkbit := SUBSTRB (v_checkcode, v_mod + 1, 1);
    93
    94 IF v_checkbit = upper(substrb(p_idcard,18,1)) THEN
    95 RETURN 1;
    96 ELSE
    97 RETURN 0;
    98 END IF;
    99 ELSE
    100 RETURN 0;
    101 END IF;
    102 ELSE
    103 RETURN 0; -- 身份证号码位数不对
    104 END CASE;
    105 EXCEPTION
    106 WHEN OTHERS
    107 THEN
    108 RETURN 0;
    109 END fn_checkidcard;
    110 /
    111 Show Err;

    2、非正则表达式写法

    --[Func_checkIdcard]--
    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		身份证号码地区码非法
    		1		身份证号码通过校验
    	*/
    	--[长度校验]--
    	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;
    
  • 相关阅读:
    SQL-排名函数
    SQL-简单查询
    SQL-判断表是否存在
    HDU1557权利选举
    Bresenham画直线,任意斜率
    LCS最长公共子序列HDU1159
    zoj1276矩阵连乘dp
    OJ的文件流操作
    dp题目
    翻纸牌 高校俱乐部 英雄会 csdn
  • 原文地址:https://www.cnblogs.com/advocate/p/2312805.html
Copyright © 2011-2022 走看看