oracle 11g写一个判断是否是身份证的函数,函数名称为:FUN_IS_IDENNO
下面是一个用于判断是否是身份证号码的Oracle 11g函数(FUN_IS_IDENNO)。身份证号码通常为18位(或者旧的15位),前17位为数字,第18位为数字或字母X,并且需要符合一定的规则,例如出生日期是否合理,校验位是否正确等。函数来自chatgpt,测试无误
函数逻辑:
- 1 输入参数:
p_idenno
,传入的身份证号码。 - 2 校验逻辑
- 判断身份证号的长度是否为18位。
- 检查前17位是否为数字。
- 验证生日部分是否为有效日期。
- 通过身份证的加权因子和校验位规则计算第18位校验码是否正确。
- 3 返回值
YES
表示身份证号有效。NO
表示身份证号无效。
在线身份证校验
测试: SELECT FUN_IS_IDENNO('610427197005053353') "是" ,FUN_IS_IDENNO('610424198505184124') "否" FROM DUAL;
CREATE OR REPLACE FUNCTION FUN_IS_IDENNO(p_idenno IN VARCHAR2)
RETURN VARCHAR2
IS
v_result VARCHAR2(3) := 'NO';
v_iden_length PLS_INTEGER;
v_birthday VARCHAR2(8);
v_year PLS_INTEGER;
v_month PLS_INTEGER;
v_day PLS_INTEGER;
v_check_digit CHAR(1);
v_check_sum PLS_INTEGER := 0;
v_weights PLS_INTEGER := 0;
v_multipliers CONSTANT SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
v_check_chars CONSTANT VARCHAR2(11) := '10X98765432';
BEGIN
-- 获取身份证号码长度
v_iden_length := LENGTH(p_idenno);
-- 校验身份证长度是否为18位
IF v_iden_length = 18 THEN
-- 校验前17位是否为数字
IF REGEXP_LIKE(SUBSTR(p_idenno, 1, 17), '^\d{17}$') THEN
-- 校验出生日期是否合理
v_birthday := SUBSTR(p_idenno, 7, 8);
v_year := TO_NUMBER(SUBSTR(v_birthday, 1, 4));
v_month := TO_NUMBER(SUBSTR(v_birthday, 5, 2));
v_day := TO_NUMBER(SUBSTR(v_birthday, 7, 2));
IF v_year BETWEEN 1900 AND EXTRACT(YEAR FROM SYSDATE) AND v_month BETWEEN 1 AND 12 THEN
IF (v_month = 2 AND v_day BETWEEN 1 AND 29 AND MOD(v_year, 4) = 0 AND (MOD(v_year, 100) <> 0 OR MOD(v_year, 400) = 0)) OR
(v_month = 2 AND v_day BETWEEN 1 AND 28 AND (MOD(v_year, 4) <> 0 OR (MOD(v_year, 100) = 0 AND MOD(v_year, 400) <> 0))) OR
(v_month IN (1, 3, 5, 7, 8, 10, 12) AND v_day BETWEEN 1 AND 31) OR
(v_month IN (4, 6, 9, 11) AND v_day BETWEEN 1 AND 30) THEN
-- 计算校验位
FOR i IN 1..17 LOOP
v_weights := TO_NUMBER(SUBSTR(p_idenno, i, 1)) * v_multipliers(i);
v_check_sum := v_check_sum + v_weights;
END LOOP;
-- 获取计算出的校验位
v_check_digit := SUBSTR(v_check_chars, MOD(v_check_sum, 11) + 1, 1);
-- 校验第18位是否正确
IF v_check_digit = SUBSTR(p_idenno, 18, 1) THEN
v_result := 'YES';
END IF;
END IF;
END IF;
END IF;
END IF;
RETURN v_result;
END FUN_IS_IDENNO;
/