结论
常见认为设为主键的条件为:
- 值唯一
- 不含空值
- 具体实施中会出现各种问题
添加主键约束的条件细则:
- 值唯一
- 数据中不含空值
- 在定义时需要not null约束(使用check约束不行)
验证实验
接下来我做了关于这个细则的验证实验:
设Student表中的列为:
- Sno( char(5),状态)
- Sname(varchar(10),null)
- Sage(int,null)
建立Student表的sql语句为:
create table Student(
Sno char(5)
Sname varchar(10)
Sage int
)
目的:想将Sno设为Student的主键。
需要根据Sno的状态分类讨论
若Sno中无null值
alter table Student
add constraint PK1 primary key(sno)
结果:会报错,因为Sno只是目前暂时没有空值,但有含null值的可能性。因此需要Sno增加约束条件,消除其含null值的可能性
思路有两种,一种通过check约束限制Sno不含空值、一种在定义Sno时限制。
- check约束限制
alter table student
add constraint C1 check(sno is not null)
成功添加check约束后再次尝试。发现仍然失败。这个方法行不通
- 定义限制
为保证实验的严谨,需要控制变量,先将刚刚的C1限制删除再进行定义限制。
alter table student
alter column sno char(5) not null
再尝试增加主键约束。发现成功添加。
若Sno中含null值
数据中含null值当然无法设置主键约束。但是在这一节可以进一步的佐证,为什么仅满足check约束无法成功添加主键约束。
- 尝试添加check约束限制
会报错,因为当前表中sno已经有null值
alter table student
add check(sno is not null)
- 强制添加check约束
通过增加with nocheck字段可以强制添加check约束。这样的效果是,不会去检查先前的空值,但会检查之后插入的元组
alter table student
with nocheck add check(sno is not null)
因此,会出现列Sno,明明有not null的check约束,但数据中仍有null值的问题。故check约束并不能保证Sno值不为null的条件,也就不能成功添加主键约束。