标准答案
- NOT NULL 用于业务上必须存在的值,避免 NULL 在比较、统计和代码分支里产生模糊语义。
- DEFAULT 适合稳定且无歧义的初始值,例如创建时间或初始状态;它不应掩盖调用方遗漏的关键业务字段。
- CHECK 适合数据行内可判断的范围和枚举约束,例如金额非负、结束时间不早于开始时间。
- UNIQUE 保护业务去重和幂等事实,例如租户内唯一编码、外部支付流水号或关系表组合。
- FOREIGN KEY 保护同库引用完整性,但删除规则、写入吞吐和跨服务边界需要结合实际决定是否使用。
题目解析
应用层校验可以给用户更友好的错误信息,也可以验证复杂业务规则;数据库约束则是最后一道防线,能覆盖后台脚本、异步任务、管理后台和未来新服务。两层都需要,而不是二选一。
约束应只表达稳定事实。把会频繁变化的运营规则、依赖外部服务的判断或复杂流程硬塞进触发器和 CHECK,往往会让发布和排查变得不可控。
常见误区
- 认为 ORM 的字段校验已经足够,允许导入脚本或管理员直接写出非法数据。
- 为了方便把所有字段设 DEFAULT,调用方漏传关键业务字段也不报错。