mcpField
D
db-constraints

db-constraints

github.com/hainrixz数据与数据库2170 次安装3 天前更新
代码仓库

关于 db-constraints

用于数据库审计的技能,检查声明式约束与可空性带来的模式正确性风险。它关注必填值、有效范围、唯一身份,以及可能未按预期生效的约束。

主要功能

  1. 01查找缺失的 NOT NULL 约束
  2. 02检查域规则是否有 CHECK 约束
  3. 03识别缺失或区分大小写的唯一性
  4. 04检测可空列上的 UNIQUE 陷阱
  5. 05查找未验证的约束

适用场景

  1. 01审查必需的外键和字段
  2. 02检查数量、价格或日期规则
  3. 03审计邮箱或用户名的唯一性
  4. 04调查软删除表中的重复风险

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hainrixz/claude-db --skill db-constraints

安装后在 Claude Code 中输入/db-constraints确认已加载。

详细介绍

db-constraints(M5)

约束是数据库保证始终成立的不变量,无论写入该行的是哪个应用、脚本或迁移。没有约束,“这永远成立”就只是一种期望,而非事实。本模块属于 design 轴(Constraints 类别)。它适用于强制执行声明式约束的引擎;文档存储则归入 Validación-schema 类别。

检查内容

  • 缺少 NOT NULL:语义上必填的列(指向必需父记录的外键、email、status、时间戳)被设为可空,允许不完整或无效的行。
  • 缺少 CHECK:未强制执行领域规则——quantity >= 0、price >= 0、status IN (...)、start_date <= end_date、email ~ '@'。应用“验证”了这些规则,但数据库没有。
  • 缺少 UNIQUE:自然键(email、username、slug、external_id)没有 UNIQUE 约束,允许出现重复值,导致联接和身份验证出错。
  • 大小写不敏感的唯一性(电子邮件):对大小写可能不同的列(例如 email)使用普通 UNIQUE,仍会允许 [email protected] 和 [email protected] 作为不同的行存在——造成身份重复。应明确指出补救方法:使用 citext 列类型,或在 lower(col) 上创建 UNIQUE 表达式索引(例如 CREATE UNIQUE INDEX ON users (lower(email))),让大小写折叠后的值发生冲突。
  • 可空 UNIQUE 陷阱:对可空列添加 UNIQUE 约束,而引擎将每个 NULL 视为不同值,导致重复值漏网(例如,用于软删除唯一性的 UNIQUE(user_id, deleted_at) 在 deleted_at 为 NULL 时失效)。建议使用部分/筛选唯一索引或 NULLS NOT DISTINCT。
  • 约束声明为 NOT VALID / NOCHECK,且从未验证。

轴与严重程度

  • 轴:design;严重程度按区间表示,绝不虚构违规数量。
  • 缺少 UNIQUE,导致身份验证/自然键允许重复身份:严重程度 4,fail/warn,置信度 directional。
  • 可空 UNIQUE 悄然允许重复值:严重程度 4,warn(不易察觉,影响大)。
  • 必填外键/列缺少 NOT NULL:严重程度 3,warn。
  • 已声明的领域规则缺少 CHECK:严重程度 2–3,warn,fixable: proposed。
  • M5 不设严重程度 5 的上限;它会影响 Constraints 类别的取值。

Tier-0 静态检查

通过 scripts/parse-schema.mjs 解析 DDL/快照:列出缺少 NOT NULL 的列;检测缺少 UNIQUE/唯一索引的自然键列名;查找成员列可空的 UNIQUE 约束(可空陷阱);扫描 quantity/price/日期范围列是否缺少 CHECK。对程序源码的解析结果保持为 directional。

Tier-1 验证查询

盘点约束和可空性:

-- $DATABASE_URL, read-only
SELECT c.table_name, c.column_name, c.is_nullable,
       tc.constraint_type
FROM information_schema.columns c
LEFT JOIN information_schema.constraint_column_usage ccu
  ON ccu.table_name = c.table_name AND ccu.column_name = c.column_name
LEFT JOIN information_schema.table_constraints tc
  ON tc.constraint_name = ccu.constraint_name AND tc.constraint_type IN ('UNIQUE','CHECK')
WHERE c.table_schema NOT IN ('pg_catalog','information_schema');

确认可空 UNIQUE 是否确实存在重复值:

SELECT user_id, count(*) FROM memberships WHERE deleted_at IS NULL
GROUP BY user_id HAVING count(*) > 1;

发现项

按照 schema/finding.schema.json 输出。示例:

  • M5.users.email_no_unique — email 没有 UNIQUE 约束;可能存在重复身份(严重程度 4,warn,轴 design,fixable: proposed)。
  • M5.memberships.over_nullable_unique — UNIQUE(user_id, deleted_at) 允许 deleted_at 为 NULL 时出现重复值(严重程度 4,warn,轴 design)。
  • M5.order_items.quantity_no_check — 没有 CHECK (quantity >= 0)(严重程度 3,warn)。
  • M5.events.user_id_nullable — 必填外键列可空(严重程度 3,warn)。 每个发现项:evidence.observed 引用列/约束 DDL 原文;verification.reproduce 是上文可运行的查询(method: ddl_parse / constraint_check / query_stat);expected_impact 按区间表示并标注置信度。

诚实性

  • 应用层验证能降低风险,但不能替代数据库约束——多个写入方(作业、管理员脚本、副本)可以绕过应用。应明确说明这一点;不要声称应用验证与数据库约束等效。
  • 可空 UNIQUE 陷阱因引擎而异(Postgres 15 之前将 NULL 视为不同值;15 起支持 NULLS NOT DISTINCT)。建议应限定于检测到的引擎/版本,不要泛化。
  • 没有 Tier-1 计数时,绝不要声称存在重复值/违规;仅凭静态检查,结论应为 directional。

评论

支持 Markdown