读书笔记:数据库约束检查的时机:为什么有时候需要"睁一只眼闭一只眼"?
我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。
本文为个人学习《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一书过程中的笔记与理解分享,仅用于学习与交流,部分内容参考原书观点并结合>实际经验进行整理。若涉及版权问题,请联系删除或沟通处理。也请大家支持购买原版书籍。
数据库约束检查的时机:为什么有时候需要"睁一只眼闭一只眼"?
大家好!今天我们来聊聊数据库中的一个有趣话题——完整性约束检查的时机问题。这就像是在工作中,有些规则是必须立即遵守的,而有些则可以稍后再处理。
默认情况:即时检查模式
想象一下,你正在给数据库下达一个指令(SQL语句)。在默认情况下,数据库会像一个严格的老师,等你把整个指令说完后,立即检查是否违反了各种规则(约束)。但它不会在你说话中途打断你。
举个例子:
UPDATE 学生表 SET 学号=学号-1;
如果数据库在修改每一行后都立即检查学号是否重复,很可能会报错。因为可能先把学号1改成了0,这时学号0已经存在了。但实际上,等所有修改完成后,学号都是唯一的。所以数据库很聪明地等整个UPDATE完成后再检查。
特殊情况:可延迟约束
但是,有些时候我们需要数据库"网开一面",暂时允许违反规则,等所有操作完成后再统一检查。这就是"可延迟约束"的用武之地。
级联更新的经典案例
最常见的场景就是"级联更新主键"。虽然专家们都建议主键应该永远不变(就像你的身份证号一样),但现实中确实会遇到需要修改主键的情况。
假设有父子两个表:
CREATE TABLE 父亲表 (身份证号 INT PRIMARY KEY);
CREATE TABLE 儿子表 (
父亲身份证 INT CONSTRAINT 父子关系
REFERENCES 父亲表(身份证号)
DEFERRABLE INITIALLY IMMEDIATE
);
正常情况下,直接修改父亲表的身份证号会报错:
UPDATE 父亲表 SET 身份证号=2; -- 立即报错!
但如果我们告诉数据库:"先别急着检查这个约束":
SET CONSTRAINT 父子关系 DEFERRED;
UPDATE 父亲表 SET 身份证号=2; -- 现在可以了
然后记得把儿子的记录也更新了:
UPDATE 儿子表 SET 父亲身份证=2;
最后再让数据库检查:
SET CONSTRAINT 父子关系 IMMEDIATE; -- 现在检查
COMMIT; -- 提交
注意事项:别滥用这个功能
虽然这个功能很强大,但要注意:
- 性能影响:可延迟的唯一约束会使用非唯一索引,可能影响查询速度
- 优化器困惑:对于可延迟的非空约束,优化器会认为该列可能为空,导致不使用索引
- 设计问题:频繁修改主键通常意味着数据库设计有问题
实际工作中的建议
- 只在真正需要时才用可延迟约束,比如处理复杂的数据迁移时
- 主键最好永远不变,如果发现经常需要修改主键,应该重新考虑设计
- 测试性能影响:使用可延迟约束后,记得检查查询计划是否变化
记住,数据库约束就像交通规则,大多数时候我们应该严格遵守,但在特殊情况下(比如救护车通行),可以适当灵活处理。关键是要知道什么时候可以"破例",以及破例后如何确保最终一切合规。
希望这篇文章能帮助你更好地理解和使用数据库约束功能!
------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)

浙公网安备 33010602011771号