l0v*_*eal 3 primary-key database-agnostic
以下完整性约束试图强制执行什么?(完整性约束是主键并在这种情况下进行检查,但我无法理解我真正应该写什么)。
解释为什么不能强制执行预期的完整性约束?
CREATE TABLE Sailors
( sid INTEGER,
sname CHAR(10),
rating INTEGER,
age REAL,
PRIMARY KEY (sid),
CHECK
( (SELECT COUNT (S.sid) FROM Sailors S)
+ (SELECT COUNT (B.bid) FROM Boats B) < 100 )
) ;
Run Code Online (Sandbox Code Playgroud)
我们在学校学习 SQL。
萨班克?bilgisayara selamlar @yguney
(注意:你已经在这个表上声明了 2 个约束,一个PRIMARY KEY约束和一个CHECK约束。答案是关于第二个。)
该CHECK约束正试图强制执行:
两个表中的行数应小于 100
所以,它应该 - 如果它有效 - 允许一个表有 50 行和其他 49 行,或 1 和 98 或 5 和 10 或......但不应该有 100 或更多。如果一个有 90,另一个应该不超过 9,并且任何尝试插入更多行的事务都应该被拒绝(引发约束错误)。
至少这看起来是它试图做的。现在的问题或更确切地说是约束的两个问题:
一个CHECK约束是行约束,在几乎所有的实现。因此,对插入或更新的每一行进行检查。这是一个实现问题,当前的 DBMS 没有实现涉及子查询的约束(除了声称这样做的 Firebird,但我还没有对其进行测试)。
有一些 DBMS 允许在CHECK约束中使用函数(并且函数可以包含子查询),因此可以“解决”限制,但这会导致各种并发问题并且问题并未真正解决。即使在那些 DBMS 中,建议也不要在CHECK约束中包含子查询。
在我看来,涉及表中多行(在本例中为所有行)ASSERTION的CHECK约束应该是,而不是约束。
其次,更严重的是,CHECK约束是对一个表的约束。它不是ASSERTION(那些是可以跨越多个表的约束)。
因此,即使存在允许CHECK约束子查询的实现,结果也将是人们所期望的。理解原因的一种方法是只有在Sailors插入或更新行时才会检查约束。这将导致这些有问题的情况:
我们在Boats表中插入 200 行。不会检查约束,因此将允许。然后我们尝试在Sailors. 检查约束并禁止该行。但是我们是否成功地执行了我们的意图?没有,因为两个表一共是200行,也就是100多行。
我们在Sailors. 到目前为止没有问题。然后是Boats表中的200 行。该约束将再次像以前一样不被检查,以便允许。然后我们尝试更新Sailors. 检查约束,我们得到一个错误。的UPDATE失败。但是我们总共还有 205 行,那么为什么更新会失败呢?
总之,这种约束有两个问题。首先,当前的实现不允许CHECK约束中的子查询,其次它应该是一个ASSERTION而不是一个CHECK约束,因为它涉及超过 1 个表。
请注意,ASSERTION到目前为止还没有 DBMS 实现(至少那些基于 SQL 的,有一些基于教程 D 的)。