知识卡片
空区间陷阱在实际查询中的呈现及DIVIDE的再次暴露
内容
[[空区间陷阱FORALL在空集合上恒为真的反直觉后果]]的抽象结论,在
“获得供应了所有紫色零件型号的供应商”这个真实查询里得到具体呈现:只要数据库
里没有任何紫色零件,FORALL PX(IF PX.COLOR='Purple' THEN ...)就因为FORALL
覆盖了一个空的”紫色零件”论域而对每个供应商都恒真——最终结果是全部供应商
(包括S5这种压根没有任何出货记录的供应商)都被判定为”满足条件”。用等价的
[[除运算符的局限性为什么应被映像关系取代]]里的DIVIDE写法
SP{SNO,PNO}DIVIDEBY PP{PNO}(PP是紫色零件的限制)重新审视这个查询,
能更精确地暴露除运算符的既有缺陷:因为这个DIVIDE表达式的候选集合来自SP
(出货记录)而不是S(供应商本身),S5根本不出现在SP里,所以这个DIVIDE
表达式永远不可能把S5包含进结果——这直接说明”获得供应了所有紫色零件型号
的供应商”这句话本身翻译成DIVIDE并不精确,DIVIDE真正表达的意思其实是”获得
至少供应了一种零件、且这些零件里恰好覆盖了全部紫色零件种类的供应商”,
这再次印证了[[除运算符的局限性为什么应被映像关系取代]]里给出的结论——
DIVIDE运算符甚至没能正确解决它字面上声称要解决的那个问题,而基于映像关系
和FORALL的等价写法(无论是关系演算的FORALL PX(...)还是Tutorial D的
S WHERE(!!SP){PNO}⊇(P WHERE COLOR='Purple'){PNO})才是真正贴合原始
查询意图的精确表达。
参考来源
- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第11章"使用逻辑
表述SQL表达式"11.6节"例5:命名子表达式"(源文件:OEBPS/text00124.html)
- 结论依据:原文明确"如果没有紫色零件,那么所有供应商都供应所有紫色零件
——即使是没有供应任何零件的供应商S5也是如此……所说的'除'是不可能返回
供应商编号S5的,因为它是从SP中而非S中提取供应商编号……这个除法的非正式
化描述不是'得到供应了所有紫色零件型号的供应商的供应商编号',而应该是
'得到至少供应了一种零件并且供应了所有紫色零件型号的供应商的供应商编号'
……除运算符并没有真正解决它本应明确解决的问题"。
- 原始内容:如果没有紫色零件,那么所有供应商都供应所有紫色零件——即使是
没有供应任何零件的供应商S5也是如此……除运算符并没有真正解决它本应明确
解决的问题。