知识卡片

UNIQUE量词及SQL近似实现

普通读书笔记卡

内容

除EXISTS/FORALL外,逻辑上还存在很多其他量词(”至少存在三个”“大多数”“奇数 个”等),实践中最重要的补充量词是UNIQUE(”仅存在一个x使得”): UNIQUE x(p(x))表示恰好只有一个满足p的实参值。UNIQUE让一些约束的表述 变得远比用FORALL套嵌套IF更清晰——[[数据库约束的分类元组约束与AND聚集表述 法]]里CX3约束(供应商编号唯一)用FORALL嵌套写法笨拙冗长 (FORALL SX(FORALL SY(IF SX.SNO=SY.SNO THEN ...))),改用UNIQUE后变成 FORALL SX(UNIQUE SY(SX.SNO=SY.SNO))——”对每个供应商SX,恰好只有一个SY 和它SNO相同”,含义直接对应键约束的本质。同理,[[SQL不支持类型约束的后果与 弥补建议]]系约束里”SP中的SNO必须出现在S中”这条外键约束,如果用UNIQUE表述 成FORALL SPX(UNIQUE SX(SX.SNO=SPX.SNO))比原来的EXISTS写法更贴近真实 意图——原来的EXISTS写法之所以”碰巧可行”,只是因为额外依赖了”{SNO}是S的 键”这条约束在背后撑腰,UNIQUE版本才是对参照约束语义更精确的直接表达。 SQL间接支持UNIQUE:UNIQUE(SELECT k FROM T WHERE p(x))(k为任意常量) 近似表达”恰有一行满足p”,其定义是”当参数表不包含任何重复行时返回TRUE, 否则FALSE”——这意味着参数表只有一行或根本没有行时UNIQUE都返回TRUE(与 UNIQUE量词”区间为空则为FALSE”的严格定义并不完全一致),书中甚至评论 AT_MOST_ONE(或NO_DUPS)才是比UNIQUE更准确的SQL运算符命名。SQL的 UNIQUE(SNO)键约束声明本质上也是CHECK(UNIQUE(SELECT SNO FROM S))的 缩写,SELECT子句里绝不能加DISTINCT(这是[[避免重复的实践规则DISTINCT与 ALL的陷阱]]里”总是用DISTINCT”这条一般性建议的一次明确例外,因为这里恰恰 需要保留重复才能让UNIQUE判断出唯一性是否被违反)。

参考来源

- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第10章"SQL与逻辑" 10.6.4节"其他量词类型"(源文件:OEBPS/text00114.html) - 结论依据:原文明确"'仅存在一个x使得',我会用UNIQUE关键字来代表它…… CONSTRAINT CX3 FORALL SX(UNIQUE SY(SX.SNO=SY.SNO))……UNIQUE sq就是 个布尔表达式,其值在sq所代表的表包含任何重复行的情况下为FALSE,否则为 TRUE……AT_MOST_ONE(或NO_DUPS)是比UNIQUE更好的SQL运算名称……在没有 指定DISTINCT的情况下会保留SELECT表达式的重复结果……DISTINCT却千万'不能 指定'"。 - 原始内容:CONSTRAINT CX3 FORALL SX(UNIQUE SY(SX.SNO=SY.SNO))…… UNIQUE sq就是个布尔表达式,其值在sq所代表的表包含任何重复行的情况下为 FALSE,否则为TRUE……DISTINCT却千万"不能指定"。