知识卡片

SQL不支持类型约束的后果与弥补建议

普通读书笔记卡

内容

SQL根本不支持[[类型约束的精确定义POSSREP与选择器THE_运算符的一一对应]]中 描述的机制——CREATE TYPE QTY AS INTEGER FINAL只能声明QTY底层用整数表示, 却没有任何语法能把”数量必须落在[0,5000]区间”这类约束绑定到类型定义本身, FINAL关键字仅仅表示这个类型不能有子类型,与约束无关。这个缺失是结构性的, 不是可以简单绕过的小问题——一旦承认某个值的合法性判断脱离了类型定义,就意味 着类型本身失去了”自证有效性”的能力。唯一的弥补手段是把本该属于类型约束的 内容,转移成数据库约束附加在使用该类型的每一处(通常是基表约束),比如把 SP表的QTY列显式加上CONSTRAINT SPQC CHECK(QTY>=QTY(0) AND QTY<=QTY(5000)) ——注意QTY(0)QTY(5000)在SQL里依然可以理解成对QTY选择器的调用,只是 “选择器”和”THE_运算符”本身都不是SQL的正式术语,SQL对它们的支持没有Tutorial D 那样”自动”。这种弥补方式的代价是显而易见的重复:数据库里每一处用到QTY类型的 地方,都要重新声明一遍原本只需要在类型定义时写一次的约束,书中承认这条建议 会造成大量重复劳动,但认为”这些重复总好过数据库中的坏数据”。这个缺失还有一个 更深远的连带后果:因为SQL无法真正约束类型本身合法的取值范围,它不得不容忍 一些逻辑上荒谬的情况存在——比如用户定义了一个SQUARE(正方形)类型,却因为 SQL没有能力约束”四条边必须等长”这条类型层面的规则,导致”非正方形的正方形” 在SQL类型系统里是合法可表示的,这个问题的根源和类型继承机制的缺失也有关, 但已超出了单纯的CHECK约束能修补的范围。

参考来源

- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第8章"SQL与约束" 8.2节"SQL中的类型约束"(源文件:OEBPS/text00090.html) - 结论依据:原文明确"SQL根本不支持类型约束!……如果你想将数量限制在某个 特定的区间,那么你就必须在每次使用类型时都指定相应的数据库约束……只要 可能,就用如同QTY示例的方式使用数据库约束弥补这个缺失。当然,此条建议 会导致大量的重复工作,但是这些重复总好过数据库中的坏数据……SQL不得不 允许一些荒谬的事情,例如,'非正方形的正方形'"。 - 原始内容:SQL根本不支持类型约束!……只要可能,就用如同QTY示例的方式使用 数据库约束弥补这个缺失……这些重复总好过数据库中的坏数据……SQL不得不允许 一些荒谬的事情,例如,"非正方形的正方形"。