4. 数据完整性审计:主键完整性检查、外键完整性检查、非空约束检查、默认值约束检查

数据完整性是数据质量的核心支柱,它确保数据在存储、传输和查询过程中保持准确、一致和可靠。本章聚焦于四种最关键的完整性约束审计:主键完整性、外键完整性、非空约束和默认值约束。通过系统化的SQL审计脚本,你可以快速定位违反约束的数据记录,并制定修复策略。

4.1 主键完整性检查

主键(Primary Key)唯一标识表中的每一行记录,其核心要求是非空且唯一。主键完整性审计的目标是发现重复键值和空值。

审计要点: 主键列不允许出现 NULL 值,且所有值必须全局唯一。任何重复或空值都意味着数据逻辑错误。

4.1.1 检查主键重复

-- 检查主键重复记录
SELECT 
    pk_column,
    COUNT(*) AS duplicate_count
FROM target_table
GROUP BY pk_column
HAVING COUNT(*) > 1;

4.1.2 检查主键空值

-- 检查主键列是否存在 NULL
SELECT 
    COUNT(*) AS null_count
FROM target_table
WHERE pk_column IS NULL;
修复建议: 对于重复记录,保留一条有效记录并归档或删除其余重复项;对于空值,需根据业务逻辑补充唯一标识或标记为异常数据。

4.2 外键完整性检查

外键(Foreign Key)维护表与表之间的引用关系,确保子表中的外键值在父表的主键中存在。外键完整性审计主要检测孤立记录(orphan records)。

4.2.1 检查孤立外键

-- 检查子表中不存在于父表的外键值
SELECT DISTINCT
    child.fk_column
FROM child_table child
LEFT JOIN parent_table parent
    ON child.fk_column = parent.pk_column
WHERE parent.pk_column IS NULL;
常见场景: 父表记录被物理删除,但子表未级联删除;或数据加载顺序错误导致子表先于父表插入。孤立记录会导致 JOIN 查询结果不完整。

4.2.2 外键完整性审计清单

检查项 SQL 核心逻辑 预期结果
孤立外键 LEFT JOIN + IS NULL 返回 0 行
外键空值(允许时) IS NULL 计数 根据业务规则判断
外键数据类型不匹配 INFORMATION_SCHEMA 对比 类型一致

4.3 非空约束检查

非空约束(NOT NULL)确保关键业务字段不能缺失。审计时需扫描所有定义为 NOT NULL 的列,找出实际存储为 NULL 的记录。

-- 动态生成非空约束检查 SQL
SELECT 
    TABLE_SCHEMA,
    TABLE_NAME,
    COLUMN_NAME,
    CONCAT('SELECT COUNT(*) AS null_count FROM ', 
           TABLE_SCHEMA, '.', TABLE_NAME, 
           ' WHERE ', COLUMN_NAME, ' IS NULL;') AS audit_sql
FROM INFORMATION_SCHEMA.COLUMNS
WHERE IS_NULLABLE = 'NO'
  AND TABLE_SCHEMA = 'your_database';
批量审计技巧: 利用 INFORMATION_SCHEMA 动态生成审计脚本,避免手动编写每个表的检查语句。将生成的 SQL 复制执行即可获得所有非空约束的违规计数。

4.4 默认值约束检查

默认值约束(DEFAULT)在插入记录时自动填充指定值。审计重点在于验证默认值是否被正确应用,以及是否存在因显式插入 NULL 导致默认值失效的情况。

4.4.1 检查默认值是否生效

-- 检查某列是否使用了默认值(以创建时间为例)
SELECT 
    COUNT(*) AS missing_default_count
FROM target_table
WHERE created_at IS NULL 
   OR created_at = '1900-01-01';  -- 常见默认值占位

4.4.2 默认值约束审计对比

审计场景 问题描述 修复措施
默认值未填充 列值为 NULL,但应有默认值 UPDATE 设置默认值或重建约束
默认值被覆盖 显式插入 NULL 覆盖了 DEFAULT 修改 INSERT 语句或添加 NOT NULL
默认值不合理 默认值不符合业务语义 修改 DEFAULT 定义

4.5 完整性审计流程总览

下图展示了数据完整性审计的完整流程,从识别约束定义到生成修复脚本,形成闭环。

数据完整性审计流程 1. 识别约束定义 2. 编写审计 SQL 3. 执行完整性检查 4. 记录违规数据 5. 生成修复脚本 约束类型 • 主键:唯一 + 非空 • 外键:引用完整性 • 非空:必填字段 • 默认值:自动填充 审计输出 • 违规记录明细 • 违规统计汇总 • 修复 SQL 脚本 • 审计报告

4.6 综合审计脚本示例

以下是一个整合了四种完整性检查的审计脚本模板,适用于单表或多表场景:

-- ============================================
-- 数据完整性审计脚本(单表示例)
-- 表名:orders
-- ============================================

-- 1. 主键完整性:检查 order_id 重复和空值
SELECT '主键重复' AS check_type, order_id, COUNT(*) AS cnt
FROM orders
GROUP BY order_id
HAVING COUNT(*) > 1
UNION ALL
SELECT '主键空值' AS check_type, NULL, COUNT(*)
FROM orders
WHERE order_id IS NULL;

-- 2. 外键完整性:检查 customer_id 是否在 customers 表存在
SELECT '孤立外键' AS check_type, o.customer_id, COUNT(*) AS cnt
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.customer_id
WHERE c.customer_id IS NULL
GROUP BY o.customer_id;

-- 3. 非空约束检查:检查必填字段
SELECT '非空违规' AS check_type, 'customer_name' AS column_name, COUNT(*) AS cnt
FROM orders
WHERE customer_name IS NULL
UNION ALL
SELECT '非空违规', 'order_date', COUNT(*)
FROM orders
WHERE order_date IS NULL;

-- 4. 默认值约束检查:检查 status 是否使用了默认值
SELECT '默认值缺失' AS check_type, COUNT(*) AS cnt
FROM orders
WHERE status IS NULL OR status = '';
最佳实践: 将审计脚本封装为存储过程或定时任务,定期(如每日/每周)自动执行并发送报告。对于发现的问题,优先通过数据修复脚本自动处理,无法自动处理的标记为人工干预。

4.7 常见问题与避坑指南

  • 主键重复误判: 联合主键需检查所有列的组合唯一性,单列检查可能遗漏。
  • 外键性能问题: 大表 LEFT JOIN 检查孤立记录时,务必在外键列上建立索引。
  • 非空约束与默认值冲突: 同时定义 NOT NULL 和 DEFAULT 时,显式插入 NULL 会导致违反非空约束,而非使用默认值。
  • 默认值类型匹配: 默认值的数据类型必须与列定义一致,否则可能导致隐式转换错误。
审计优先级: 主键完整性 > 外键完整性 > 非空约束 > 默认值约束。主键和外键问题直接影响数据关联和查询准确性,应优先修复。