知识卡片
SQL视图可更新性规则的复杂混乱及CHECK选项
内容
针对[[视图更新失败的本质是违反黄金规则或赋值原理]]里”违反用户不知情约束”
这类问题,SQL提供了CHECK OPTION机制:给视图声明WITH CASCADED CHECK OPTION
后,任何对该视图的更新都必须符合视图定义表达式本身——否则会被拒绝,而不是
默默地把行写进底层基表却让它”从视图角度看不见”(这种默认行为本身就直接违反
赋值原理:用户认为自己插入了一行,但从视图的视角看这次插入其实什么都没
发生)。实践建议是只要视图被认定为可更新,就应该指定CASCADED(这是默认项,
不必显式写出);CASCADED的替代项LOCAL语义相当古怪,作者建议直接不用。但SQL
判定”一个视图是否可更新”的规则本身极其复杂、零散分布在标准各处,涉及大量
彼此关联的底层概念(可更新列、叶子表、query term等),书中举了一个反例说明
这套规则甚至可能不自洽——形式上通过所有条件判定为”可更新”的一个UNION ALL
视图,实际执行更新却明显不正确。SQL还进一步区分了可更新、潜在可更新、简单
可更新、可插入这4种细分状态(标准正式定义了这些术语却没有解释直觉含义),
大致规律是”可更新”对应UPDATE/DELETE、”可插入”对应INSERT,且一个视图除非
先是可更新的才可能可插入,但某些视图却允许DELETE却拒绝INSERT(或反过来),
导致DELETE和INSERT不再互为逆运算——这正是对[[互换性原理及其重要推论]]的
又一处具体违反。作为参照,一个SQL视图若满足以下全部条件则肯定可更新:定义
表达式是单一SELECT(不是UNION/INTERSECT/EXCEPT的组合);SELECT子句用ALL
而非DISTINCT;展开所有星号后SELECT项列表每项都是简单列名(可限定/可AS,且
每列至多出现一次);FROM子句形如FROM T[AS...]且T本身是可更新表;若有WHERE
子句则不包含对FROM里同一张表T的子查询;没有GROUP BY或HAVING。