约束的作用:
- 面临的问题
1)某列必须有值而且唯一
2)某列的取值受到另一列取值的限制
约束的类型:
- PRIMARY KEY 主键约束
- UNIQUE KEY 唯一键约束
- NOT NULL 非空约束
- REFERENCES 外键
- CHECK 检查约束
- PRIMARY KEY--主键约束(一张表只能存在一个主键约束)
主键约束解决的问题:
- 不允许表中有NULL的数据;
- 不允许表中有重复数据;
主键约束的两种形式及异同
1)列级约束
create table test (
c1 number(10) constraint pk_test_c1 primarykey,
c2 number(10)
);
禁止往主键列中插入NULL值
SQL> insert intotest values(null,null);
insert into testvalues(null,null)
ORA-01400:无法将 NULL 插入 ("SCOTT"."TEST"."C1")
禁止往主键列中插入重复值
SQL> insert intotest values(1,1);
1 row inserted
SQL> insert intotest values(1,2);
insert into testvalues(1,2)
ORA-00001:违反唯一约束条件 (SCOTT.PK_TEST_C1)
2)表级约束
create table test1(
c1 number(10),
c2 number(10),
c3 number(10),
constraintpk_test1_c1_c2 primary key (c1,c2)
);
联合主键特点:
1)联合主键中的每一列都不能为空;
2)多列联合唯一(不能存在重复数据)
对于1)的举例说明:
SQL> insert intotest1 values(null,1,1);
insert into test1values(null,1,1)
ORA-01400:无法将 NULL 插入 ("SCOTT"."TEST1"."C1")
SQL> insert intotest1 values(1,null,1);
insert into test1values(1,null,1)
ORA-01400:无法将 NULL 插入 ("SCOTT"."TEST1"."C2")
SQL> insert intotest1 values(1,1);
insert into test1values(1,1)
ORA-00947:没有足够的值
SQL> insert intotest1(c1,c2) values(1,1);
1 row inserted
SQL> select *from test1;
C1 C2 C3
---------------------- -----------
1 1
对于2)的 举例说明:
SQL> insert intotest1(c1,c2) values(2,2);
1 row inserted
SQL> select *from test1;
C1 C2 C3
---------------------- -----------
1 1
1 2
2 2
SQL> insert intotest1(c1,c2) values(2,2);
insert intotest1(c1,c2) values(2,2)
ORA-00001:违反唯一约束条件 (SCOTT.PK_TEST1_C1_C2)
给存在的表增加或者删除约束
增加主键约束:
1)
SQL> select *from test1;
C1 C2 C3
---------------------- -----------
1 1
1 2
2 2
2 2
SQL> alter tabletest1 add constraint pk_test1_c1_c2 primary key(c1,c2);
alter table test1add constraint pk_test1_c1_c2 primary key(c1,c2)
ORA-02437:无法验证 (SCOTT.PK_TEST1_C1_C2) - 违反主键
当表中数据违反唯一性约束时,便会报出该错误
2)所以我们在增加增加约束时,应该先校验一下,看目前表中的 数据是否满足主键 约束条件
SQL> selectcount(*),c1,c2 from test1 group by c1,c2 having count(*)>1;
COUNT(*) C1 C2
--------------------- -----------
2 2 2
删除数据
增加主键
alter table test1add constraint pk_test1_c1_c2 primary key(c1,c2)
删除主键约束:
alter table test1drop primary key;
- 非空约束--NOT NULL
作用:
- 不允许该列为空;
- 只有列级约束的形式;没有表级约束的形式。
createtable test3(
c1number(10),
c2number(10) not null,
c3number(10)
);
SQL>select * from test3;
C1 C2 C3
---------------------- -----------
SQL>insert into test3 values(1,null,1);
insertinto test3 values(1,null,1)
ORA-01400:无法将 NULL 插入 ("SCOTT"."TEST3"."C2")
SQL>insert into test3 values(1,1,1);
1row inserted
SQL>select * from test3;
C1 C2 C3
---------------------- -----------
1 1 1
删除NOT NULL非空约束
SQL>alter table test3 modify(c2 null);
Tablealtered
SQL>desc test3;
NameType Nullable Default Comments
-------------- -------- ------- --------
C1 NUMBER(10) Y
C2 NUMBER(10) Y
C3 NUMBER(10) Y
增加NOT NULL约束
altertable student modify (name not null);
- 唯一键--UNIQUE
createtable test4(
c1number(10) unique,
c2number(10) not null,
c3number(10) unique
);
SQL>insert into test4 values(null,1,null);
1row inserted
SQL>select * from test4;
C1 C2 C3
---------------------- -----------
1
SQL>insert into test4 values(null,1,1);
1row inserted
SQL>select * from test4;
C1 C2 C3
---------------------- -----------
1
1 1
SQL>insert into test4 values(1,1,1);
insertinto test4 values(1,1,1)
ORA-00001:违反唯一约束条件 (SCOTT.SYS_C0012944)
SQL>insert into test4 values(1,1,2);
1row inserted
SQL>select * from test4;
C1 C2 C3
---------------------- -----------
1
1 1
1 1 2
总结:
1.主键约束:一个表只能有一个主键约束。主键可以是单个字段,也可以是多个字段。无论是哪种情况,其所有字段都是NOT NULL。
2.Unique约束:一个表可以有多个Unique约束,Unique的字段可以为NULL。
3.主键与Unique:不同点在于一个表只能有一个主键约束,但是可以有多个Unique约束;主键所有字段都是notnull,unique可以是null。相同点在于都能保证唯一性。
4、在存在非空数据时UNIQUE 唯一键约束能够保证数据的唯一,但是当该列为null 时可以添加多条null的数据。
5、唯一键同样存在表级约束和列级约束。
删除唯一键:
添加唯一键:
altertable test4 add constraint uk_c2 unique(c2);
类似联合主键,UNIQUE 会存在联合唯一键。
- 外键约束--FOREIGN KEY REFERENCES
创建主表(student)
create table student(
id number not null,
name varchar2(50),
constraint pk_student_id primary key(id)
);
创建子表(class)
create table class(
class_id number not null,
grade number not null,
constraint fk_class_id foreign key(class_id)references student(id)
);
分别往主表和子表插入数据
SQL>select * from student;
ID NAME
------------------------------------------------------------
1 张三
2 李四
SQL>insert into class values(3,1);
insertinto class values(3,1)
ORA-02291: 违反完整约束条件 (SCOTT.FK_CLASS_ID) - 未找到父项关键字
SQL>insert into class values(1,1);
1row inserted
SQL>select * from class;
CLASS_ID GRADE
--------------------
1 1
SQL>delete from student a where a.id=1;
deletefrom student a where a.id=1
ORA-02292: 违反完整约束条件 (SCOTT.FK_CLASS_ID) - 已找到子记录
- 如果在创建外键约束时,如果使用on delete cascade,则删除父表中数据时,不报错而直接把子表关联的数据删除。
SQL>alter table class drop constraint fk_class_id;
Tablealtered
SQL>alter table class add constraint fk_class_id foreign key(class_id) referencesstudent(id) on delete cascade;
Tablealtered
SQL>delete from student a where a.id=1;
1row deleted
SQL>select * from student;
ID NAME
------------------------------------------------------------
2 李四
SQL>select * from class;
CLASS_ID GRADE
--------------------
- 如果要删除父表,则需要加上cascade constraints,此时子表的foreign key被去除,表中记录保持不变。
SQL>insert into class values(2,2);
1row inserted
SQL>select * from class;
CLASS_ID GRADE
--------------------
2 2
SQL>drop table student;
droptable student
ORA-02449: 表中的唯一/主键被外键引用
如果要删除则必须加上cascade constraints
SQL>drop table student cascade constraint;
Tabledropped
SQL>select * from student;
select* from student
ORA-00942:表或视图不存在
SQL>select * from class;
CLASS_ID GRADE
--------------------
2 2
总结:
- 外键必须为另外一张表(父表)的主键或者唯一索引。如果要添加记录,而父表中没有则报错。(ORA-02291)
- 反之,如果要删除父表中的记录,而子表中有记录,也会报错。(ORA-02292)
- 但是如果在创建外键约束时,如果使用on delete cascade,则删除父表中数据时,不报错而直接把子表关联的数据删除。
- 如果要删除父表,则需要加上cascade constraints,此时子表的foreign key被去除,表中记录保持不变。
- 检查约束--CHECK
- CHECK 约束用于限制列中的值的范围。
- 如果对单个列定义 CHECK 约束,那么该列只允许特定的值。
- 如果对一个表定义 CHECK 约束,那么此约束会在特定的列中对值进行限制。
创建一个表级约束:
create table pupil(
id number not null,
lsname varchar2(50) not null,
fsname varchar2(50),
city varchar2(50),
constraint chk_pupil check(id>0 andcity='guangshan')
);
SQL>insert into pupil values(-1,'a','a','guangshan');
insertinto pupil values(-1,'a','a','guangshan')
ORA-02290: 违反检查约束条件 (SCOTT.CHK_PUPIL)
SQL>insert into pupil values(1,'a','a','guangshan');
1row inserted
- 对已有的表删除、增加校验约束
altertable pupil drop constraint chk_pupil;
altertable pupil add constraint chk_pupil_ls check(lsname='A');