MySQL 查询不正确身份证号的方法
基本身份证验证查询
SELECT *
FROM base_student
WHERE -- 长度不是15位或18位LENGTH(idcard) NOT IN (15, 18)OR-- 包含非数字和X字符idcard REGEXP '[^0-9X]'OR-- 18位身份证但最后一位不是数字或X(LENGTH(idcard) = 18 AND RIGHT(idcard, 1) NOT REGEXP '[0-9X]')OR-- 15位身份证但包含非数字字符(LENGTH(idcard) = 15 AND idcard REGEXP '[^0-9]');
更严格的身份证验证查询
如果你需要更严格的验证(包括校验位验证),可以使用以下查询:
SELECT *
FROM base_student
WHERE -- 基本格式验证(LENGTH(idcard) NOT IN (15, 18)OR idcard REGEXP '[^0-9X]'OR (LENGTH(idcard) = 18 AND RIGHT(idcard, 1) NOT REGEXP '[0-9X]')OR (LENGTH(idcard) = 15 AND idcard REGEXP '[^0-9]'))OR-- 日期部分验证(针对18位身份证)(LENGTH(idcard) = 18 AND (-- 提取日期部分并验证STR_TO_DATE(SUBSTR(idcard, 7, 8), '%Y%m%d') IS NULLOR SUBSTR(idcard, 7, 8) < '19000101'OR SUBSTR(idcard, 7, 8) > DATE_FORMAT(NOW(), '%Y%m%d')))OR-- 日期部分验证(针对15位身份证)(LENGTH(idcard) = 15 AND (-- 提取日期部分并验证STR_TO_DATE(CONCAT('19', SUBSTR(idcard, 7, 6)), '%Y%m%d') IS NULLOR CONCAT('19', SUBSTR(idcard, 7, 6)) < '19000101'OR CONCAT('19', SUBSTR(idcard, 7, 6)) > DATE_FORMAT(NOW(), '%Y%m%d')));
分区验证查询(推荐)
如果你想知道具体哪些记录不符合哪种验证规则,可以使用以下分区验证:
SELECT id,name,idcard,CASE WHEN LENGTH(idcard) NOT IN (15, 18) THEN '长度错误'WHEN idcard REGEXP '[^0-9X]' THEN '包含非法字符'WHEN LENGTH(idcard) = 18 AND RIGHT(idcard, 1) NOT REGEXP '[0-9X]' THEN '18位身份证最后一位错误'WHEN LENGTH(idcard) = 15 AND idcard REGEXP '[^0-9]' THEN '15位身份证包含非数字字符'WHEN LENGTH(idcard) = 18 AND STR_TO_DATE(SUBSTR(idcard, 7, 8), '%Y%m%d') IS NULL THEN '18位身份证日期部分无效'WHEN LENGTH(idcard) = 15 AND STR_TO_DATE(CONCAT('19', SUBSTR(idcard, 7, 6)), '%Y%m%d') IS NULL THEN '15位身份证日期部分无效'ELSE '其他错误'END AS error_type
FROM base_student
WHERE LENGTH(idcard) NOT IN (15, 18)OR idcard REGEXP '[^0-9X]'OR (LENGTH(idcard) = 18 AND RIGHT(idcard, 1) NOT REGEXP '[0-9X]')OR (LENGTH(idcard) = 15 AND idcard REGEXP '[^0-9]')OR (LENGTH(idcard) = 18 AND STR_TO_DATE(SUBSTR(idcard, 7, 8), '%Y%m%d') IS NULL)OR (LENGTH(idcard) = 15 AND STR_TO_DATE(CONCAT('19', SUBSTR(idcard, 7, 6)), '%Y%m%d') IS NULL);
身份证校验位验证(高级)
对于18位身份证,还可以验证校验位是否正确:
SELECT *
FROM base_student
WHERE LENGTH(idcard) = 18AND (-- 校验位验证CASE WHEN idcard REGEXP '^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9X]$' THEN-- 计算校验位(SUBSTR('10X98765432', MOD(SUM(SUBSTR(idcard, 1, 1) * 7 +SUBSTR(idcard, 2, 1) * 9 +SUBSTR(idcard, 3, 1) * 10 +SUBSTR(idcard, 4, 1) * 5 +SUBSTR(idcard, 5, 1) * 8 +SUBSTR(idcard, 6, 1) * 4 +SUBSTR(idcard, 7, 1) * 2 +SUBSTR(idcard, 8, 1) * 1 +SUBSTR(idcard, 9, 1) * 6 +SUBSTR(idcard, 10, 1) * 3 +SUBSTR(idcard, 11, 1) * 7 +SUBSTR(idcard, 12, 1) * 9 +SUBSTR(idcard, 13, 1) * 10 +SUBSTR(idcard, 14, 1) * 5 +SUBSTR(idcard, 15, 1) * 8 +SUBSTR(idcard, 16, 1) * 4 +SUBSTR(idcard, 17, 1) * 2), 11) + 1, 1) <> UPPER(RIGHT(idcard, 1))ELSE TRUEEND);