1.3 仅限基表:补偿性操作
现在,为了确保之前章节提到的约束在后续的某些特定更新升级完成后依然有效,就需要进行相应的补偿性操作。通常情况下,补偿性操作也称为补偿操作,是一种由数据库管理系统自动执行的额外更新(不包括用户自行请求的更新),其目的就是为了避免完整性冲突的发生[5]。级联删除就是一个典型的例子[6]。事实上,有一点我们要明确,对于现在手上这个例子来说,我们很需要在进行DELETE操作时应用级联方式。具体来说,不管是从表LS,还是表NLS中,删除数据都需要级联以使得表S中相同的数据行也能够被删除。于是我们可以设想一些补偿性操作,其实就是级联删除规则,观察以下伪代码。
ON DELETE d FROM LS : DELETE d FROM S ;
ON DELETE d FROM NLS : DELETE d FROM S ;
同样,从表S中删除行也需要级联以使表LS或表NLS中同样的行一并被删除。
ON DELETE d FROM S : DELETE ( d WHERE CITY = ‘London’ ) FROM LS ,
DELETE ( d WHERE CITY <> ‘London’ ) FROM NLS ;
这里我要特别提醒的是,任何想对并不存在的行进行删除的尝试都是无效的,因此我们可以将圆括号内的表达式直接替换为d。不过从定义方式的角度来讲,圆括号内的定义表达方式更好,因为它们对变量的定义更加具体明确。
类似地,我们也需要为INSERT操作设定补偿性操作,即级联插入规则。
ON INSERT i INTO LS : INSERT i INTO S ;
ON INSERT i INTO NLS : INSERT i INTO S ;
ON INSERT i INTO S : INSERT ( i WHERE CITY = ‘London’ ) INTO LS ,
INSERT ( i WHERE CITY <> ‘London’ ) INTO NLS ;
```
当然,级联插入的概念并不经常与外键约束联系在一起,但这个概念并没有问题。重要的是我们要认清补偿性操作并不总是以简单级联的形式出现。我们在本章中所讨论的仅仅是个简单的例子,以便大家理解概念,在实际工作中则需要根据具体情况来应用各种更复杂的形式,在后面的章节我们也会有一些案例给大家展示。
在当前的范例中,UPDATE操作可以被看作DELETE和INSERT的结合。因此,简单地说,对本范例的必要的补偿性操作就是对DELETE和INSERT操作规则设定的总和。例如,考虑下面表S上面的UPDATE操作。
```javascript
UPDATE S
SET CITY = ‘Oslo’
WHERE SNO = ‘S1’ ;
产生的结果如下。
1.表S中供应商S1现有的行被删除,CITY值为Oslo的新行被插入到这个表中。
2.表LS中供应商S1现有的行同样被删除,这是因为从表S到表LS的级联删除规则。同时因为CITY值为OSlo,这个供应商的新行被插入到表NLS,这次则是应用了级联插入规则。换句话说,供应商S1的行从表LS迁移到了表NLS(当然,这只是笼统来看)。
现在我们假设原来的UPDATE操作是在表LS中执行,而不是在表S中执行的。
UPDATE LS
SET CITY = ‘Oslo’
WHERE SNO = ‘S1’ ;
产生的结果如下。
1.供应商S1现有的行从表LS中删除。
2.尝试向表LS插入供应商为S1的新行,CITY值为Oslo。但是该尝试会失败,因为它违反了表LS中CITY值必须为London的约束。因此这次UPDATE操作整体失败,之前已经完成的步骤(在表LS中删除供应商S1的行)被撤销,最后的结果就是数据库保持不变。