4.4.2 not null约束
正如我们在第3章中讨论过的,空值是所有域的成员,因此在默认情况下是SQL
中每个属性的合法值。然而对于一些属性来说,空值可能是不合适的。
考虑student
关系中的一个元组,其中name
是null
。这样的元组给出了一个未知学生的学生信息;因此它不含有有用的信息。
类似地,我们不会希望系的预算为null
。
not null约束写法
在这些情况下,我们希望禁止空值,我们可以通过如下声明来通过限定属性name
和budget
的域来排除空值:
1 | name varchar(20) not null |
主码不用声明not null
not null
声明禁止在该属性上插入空值。任何可能导致向一个声明为not null
的属性插入空值的数据库修改都会产生错误诊断信息。
许多情况下我们希望避免空值。尤其是SQL
禁止在关系模式的主码
中出现空值
。因此,在我们的大学例子中,在department
关系上如果声明属性dept_name
为department
的主码,那它就不能为空。因此主码(dept_name
)不必显式地声明为not null
4.4.3 unique约束
SQL
还支持下面这种完整性约束:
1 | unique(A1,A2,...,An) |
unique声明的属性形成候选码
unique
声明指出属性A1,A2,...,An
形成了一个候选码;
即在关系中没有两个元组能在所有列出的属性A1,A2,...,An
上取值相同。
unique中的属性可以为null
然而候选码属性
可以为null
,除非它们已被显式地声明为not null
。
回忆一下,空值不等于其他的任何值。(这里对空值的处理与3.8.4
节中定义的unique
结构一样。)
4.4.4 check子句
当应用于关系声明时, check(P)
子句指定一个谓词P,
关系中的每个元组都必须满足谓词P
。
通常用check
子句用来保证属性值满足指定的条件
。
实际上创建了一个强大的类型系统。例如,在创建关系department
的create table
命令中的check(budget>0)
子句将保证budget
上的取值是正数。
实例 在建表时指定check子句
作为另一个例子,考虑如下语句:
1 | create table section ( |
这里我们用check
子句模拟了一个枚举类型,通过指定semester
必须是’Fall
‘、 Winter
、 Spring
或’ Summer
‘中的一个来实现。这样, check
子句允许以有力的方式对属性域加以限制。
验证
以下在MySQL 8.0
中验证通过
不满足check子句的插入会被拒绝
1 | insert into section |
这个插入语句试图向semester
属性赋值3333
,这不满足check
子句的要求,系统会拒绝插入操作.
1 | mysql> insert into section values('1111','2222','3333',2019,'大楼','4444','5555'); |
满足check子句的插入才会通过
1 | insert into section |
1 | mysql> insert into section values('1111','2222','Fall',2019,'大楼','4444','5555'); |
目前check子句谓词不能是子查询
根据SQL
标准, check
子句中的谓词可以是包括子查询在内的任意谓词。然而,当前还没有一个广泛使用的数据库产品允许check
子句包含子查询的谓词。