知识卡片
SQL字符序与"相等但可区分"的值
内容
SQL中字符串的比较规则由字符序(collation)决定,而字符序存在两个容易被忽视的 变数。第一个变数是PAD SPACE与NO PAD的选择:若采用PAD SPACE,字符串”AB”和”AB “ (末尾多一个空格)这两个明显不同的字符串会被判定为”比较上相等”;书中明确建议 尽量使用NO PAD,避免这种因为空格填充造成的虚假相等(注意这个选择只影响比较, 不影响赋值)。第二个变数是大小写不敏感这类字符序(如CASE_INSENSITIVE)会让 明显不同的字符值比较为相等(比如小写”p2”和大写”P2”)。这两种情况共同指向一个 被作者命名为”相等但可区分”(equal but distinguishable)的值对概念:两个值本身 确实不同(可区分),但在相等比较运算里却返回TRUE。这不只是一个理论上的怪癖—— 它会实际影响MATCH、LIKE、UNIQUE、UNION、JOIN等大量隐式依赖相等判断的运算, 一个具体后果是外键约束检查也可能被这种”相等但可区分”的字符序悄悄放宽(比如大小写 不同、末尾多个空格的两个值仍被判定满足外键匹配)。更麻烦的是,涉及UNION、 INTERSECT、GROUP BY、DISTINCT这类需要从多个”相等但可区分”的候选值中选出一个作为 结果的运算,SQL标准本身没有给出确定性规则,导致同一查询在数据完全不变的情况下 可能返回不同结果(SQL称之为”可能非确定性的”),书中强调这类表达式绝不能出现在 完整性约束里,因为会造成不可预期的更新失败。
参考来源
- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第2章"类型和域"2.8节
"SQL中的字符序"(源文件:OEBPS/text00026.html)
- 结论依据:原文明确"如果使用PAD SPACE则两者可认为是'比较上相等的'……对确定的
字符序,即使字符a和b不同,比较表达式a=b也可能返回TRUE……我会用'相等但可区分
(equal but distinguishable)'表示这样的值对""这种表达式不允许出现在完整性
约束中……因为它们会导致不可预期的更新失败"。
- 原始内容:如果使用PAD SPACE则两者可认为是"比较上相等的"……我会用"相等但可区分
(equal but distinguishable)"表示这样的值对……这种表达式不允许出现在完整性
约束中,因为它们会导致不可预期的更新失败。