知识卡片
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约束能修补的范围。