知识卡片

选择器与THE_运算符如何同时满足域检查与域检查重载

结构图卡

内容

关系模型的一条基本规则是:只有两个值来自同一个域(类型)时才能比较相等,比如 供应商编号(SNO类型)和零件编号(PNO类型)即使底层都用CHAR字符串表示,也不能 直接比较,因为它们是不同种类的事物。但这条规则会遇到一个真实困境:如果供应商 编号和顾客编号恰好都可能用同样的字符串表示,用户有时确实需要问”有没有我们的 顾客同时也是供应商”这类跨类型的合理查询,系统不能一刀切地拒绝所有跨域比较。 Codd曾提出”域检查重载”(DCO)机制试图解决这个矛盾,但书中指出该方案本身逻辑 不自洽(比如 P.WEIGHT=SP.QTY 与语义等价的 P.WEIGHT-SP.QTY=0 却被判定 一个合法一个不合法),本质是混淆了类型和表示。真正干净的解法依赖两个每个类型 都必须定义的运算符:选择器(selector,把某种物理表示——如字符串’X4’——转换成 该类型的一个确定取值,例如 SNO('X4'))和THE_运算符(做相反方向的转换,把某个 类型的取值转换回可比较的表示,例如 THE_SC(S.SNO))。当用户写 S.SNO='X4' 时, 系统隐式调用选择器把字符串型转为SNO类型再比较,这就同时提供了两种效果:默认 情况下坚持严格的域检查(不同类型不能直接比较),需要跨域比较时用户可以显式调用 THE_运算符把两个不同类型的取值都转换成同一种可比较的表示,两个需求由同一套正交 机制满足,而不需要引入语义不一致的特例规则。

结构图

flowchart LR
    A["字符串字面值 'X4'"] -->|选择器 SNO| B[SNO类型确定取值]
    C["字符串字面值 'X4'"] -->|选择器 PNO| D[PNO类型确定取值]
    B -->|"THE_SC()"| E[可比较的字符串表示]
    D -->|"THE_PC()"| F[可比较的字符串表示]
    E -->|"='"| F
    B -.同类型直接比较合法.-> B2["S.SNO = SNO('X4')"]
    D -.同类型直接比较合法.-> D2["P.PNO = PNO('X4')"]

参考来源

- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第2章"类型和域"2.2节 "相等性比较"(源文件:OEBPS/text00020.html) - 结论依据:原文明确"只有两个值来自于同一个域时才可以在关系模型中比较它们是否 相等……系统至少知道有那么一个运算符(即SNO选择器),实际上会执行CHAR到SNO的 转换……这里描绘的(包含选择器和THE_运算符的)机制实际上同时提供了两种检查 方法:(a)我们首先想要的域检查;(b)在需要时重载域检查……而域检查重载并没有 真正完成此工作。事实上,它根本讲不通,因为它混淆了类型和表示"。 - 原始内容:只有两个值来自于同一个域时才可以在关系模型中比较它们是否相等……这里 描绘的(包含选择器和THE_运算符的)机制实际上同时提供了两种检查方法……而域检查 重载并没有真正完成此工作,因为它混淆了类型和表示。