知识卡片
关系赋值统一INSERT/DELETE/UPDATE与赋值原理
内容
[[关系值与关系变量的区分及DELETE的本质]]中已提到DELETE本质是关系赋值的简写,
本节把这个等价关系系统化地展开到INSERT:INSERT R rx;定义为R := R UNION
rx;的简写;DELETE R WHERE bx;是R := R WHERE NOT(bx);(等价于R := R
MINUS(R WHERE bx))的简写。这个等价关系有一个容易被忽视的语义后果:既然
INSERT本质是并运算,插入一条已经存在的元组不会报错,只是并运算”吸收”了这个
重复、什么都不会发生;如果确实需要”插入必须是全新元组,重复则报错”这种更严格
的语义,Tutorial D专门提供了D_INSERT(不相交INSERT,底层用D_UNION实现,要求
两侧运算元不能有相同元组);对称地,普通DELETE允许”删除不存在的元组”(同样
什么都不会发生),若要求”待删除的元组必须先存在,否则报错”则要用I_DELETE
(底层用I_MINUS,即包含差实现)。SQL在INSERT/DELETE/UPDATE上和Tutorial D的
关键区别在于:SQL的INSERT语义上更接近UNION ALL而非UNION,因此在没有键约束
的表里插入重复行是允许的;SQL完全没有真正意义上的关系赋值运算符,最接近的
写法是先DELETE FROM T;再INSERT INTO T(...) tx;两条语句的序列,但这个
序列可能会失败(比如表T有NOT NULL约束、tx里某行违反约束),而理论上对应的
单次关系赋值本应直接成功或直接失败,不会出现”先删干净、再插入失败、表变空了”
这种中间状态。本节末尾提出的赋值原理(Assignment Principle)是所有赋值运算
(不限于关系赋值,是计算领域的通用原则)必须满足的底线:把值v赋给变量V之后,
比较式v=V必须返回TRUE——[[NULL违反信息原理及SQL自身3VL支持的内在缺陷]]中
B=UNKNOWN总是返回null的诡异行为,正是SQL自己违反这条基本原理的一个具体例证。