SQL 完整性约束

完整性约束
1.掌握约束的主要作用;
2.掌握5中约束的使用形式;
3.理解约束的修改操作;
4.可以同坐数据字典表查看约束信息;

完整性约束是保证用户对数据库所做的修改不会破坏数据的一致性,是保护数据正确性和相容性的一种手段。

维护完整性
在一个DBMS之中,为了能够维护数据库的完整性,必须能够提供以下的几种支持:
提供定义完整性约束条件机制:在数据表上定义规则,这些规则是数据库中的数据必须满足的语义约束条件;
提供完整性检查的方法:在更新数据库时检查更新数据是否满足完整性约束条件;
违约处理:DBMS发现数据违反了完整性约束条件后要采取的违约处理行为,如拒绝(NO ACTION)执行该操作,或者级联(CASCADE)执行其他操作

主要约束分类在开发之中可以使用以下的五种约束进行定义:
非空约束:如果使用了非空约束的话,则以后此字段的内容不允许设置成null;
唯一约束:即:此列的内容不允许出现重复;
主键约束:表示一个唯一的标识,例如:人员ID不能重复,且不能为空;
检查约束:用户自行编写设置内容的检查条件;
主-外键约束(参照完整性约束):是在两张表上进行的关联约束,加入关联约束之后就产生父子的关系。

1、非空约束:NK
在正常情况下,NULL是每个属性的合法数据值。如果说现在某个字段不能为NULL,且必须存在数据,那么就可以依靠非空约束来进行控制,这样在数据更新时,此字段的内容出现NULL时就会产生错

例:定义member表,其中姓名不允许为空
drop table member purge ;
create table member(mid number ,name varchar2(200) not null);

向member表中增加正确的数据
insert into member(mid,name) values (1,‘Ken’) ;
向member表中增加错误的数据(两种语句的执行结果一样)明确设置name字段为null:
insert into member(mid,name) values (3,null) ; 结果报错,无法将null插入
不设置name字段的内容:结果报错,无法将null插入
insert into member(mid) values (3) ;
非空约束不允许字段为null;
非空约束出现错误时会提示完整的错误位置
2、唯一约束
违反唯一约束报错信息:ora00001
唯一约束(UNIQUE,简称UK)表示的是在表中的数据不允许出现重复的情况,
例如:每一位成员都肯定有自己的email地址,而这个地址肯定是不重复的。 drop table member purge ;
create table member(mid number ,name varchar2(200) not null ,email varchar2(50) unique);
唯一约束 —— 范例
为唯一约束指定一个名字
drop table member purge ;
create table member(mid number ,name varchar2(200) not null
,email varchar2(50) ,constraint uk_email unique (email));
创建member表,在email字段上设置唯一约束
drop table member purge ;
create table member(mid number ,name varchar2(200) not null ,email varchar2(50) unique)
向member表中增加正确记录
insert into member (mid,name,email) values(1,‘Tony’,‘tt@163.com’) ;
commit;
向member表中增加错误的纪录
insert into member (mid,name,email) values(2,‘Mark’,‘tt@163.com’) ;
ORA-00001: 违反唯一约束条件 (SPORT.SYS_C0011403)
为唯一约束指定一个名字
drop table member purge ;
create table member(mid number ,name varchar2(200) not null ,email varchar2(50)
,constraint uk_email unique (email)) ;
此时,再次执行两条插入语句,则错误提示将变为以下的内容
插入两条包含null的记录
insert into member (mid,name,email) values(10,‘vdata’,null) ;

insert into member (mid,name,email) values(20,‘enmo’,null) ;

select * from member;
发现两条均已插入
小结
唯一约束可以设置NULL;
唯一约束的列不允许重

3、主键约束:PK
如果一个字段即要求唯一,又不能设置为null,则可以使用主键约束(主键约束 = 非空约束 + 唯一约束),主键约束使用PRIMARY KEY(简称PK)进行指定,
例如:在member表中的mid字段应该表示一个成员的唯一编号,而这个编号即不能为空,也不能重复
设置member表中的mid为主键
drop table member purge ;
create table member(mid number primary key ,name varchar2(200) not null ,email varchar2(50)
,constraint uk_ email unique (email));

主键约束 —— 范例
指定主键约束的名称
drop table member purge ;
create table member(mid number ,name varchar2(200) not null ,email varchar2(50) ,
constraint pk_mid primary key (mid),constraint uk_email unique (email));

复合主键
在实际的开发之中,一般在一张表中只会设置一个主键,但是也允许为一张表设置多个主键,这个时候将其称为复合主键。
在复合主键中,只有两个主键字段的内容完全一样,才会发生违反约束的错误。
drop table member purge ;
create table member(mid number ,name varchar2(200) not null ,email varchar2(50) ,
constraint pk_mid_name primary key (mid,name) ,constraint uk_email unique (email)) ;

设置member表中的mid为主键
drop table member purge ;
create table member(mid number primary key ,name varchar2(200) not null ,email varchar2(50)
,constraint uk_email unique (email)) ;

范例:将mid设置为null
insert into member(mid,name,email) values(null,
‘Tony’,‘Tony@163.com’);
错误报告 -
ORA-01400: 无法将 NULL 插入 (“SPORT”.“MEMBER”.“MID”)

范例:插入重复的mid
insert into member (mid,name,email) values(1,‘Ken’,‘Ken@163.com’) ;

insert into member (mid,name,email) values(1,‘Mark’,‘Mark@163.com’);
错误报告 -
ORA-00001: 违反唯一约束条件 (SPORT.SYS_C0011415)

范例:指定主键约束的名称
drop table member purge ;
create table member(mid number ,name varchar2(200) not null ,email varchar2(50) ,
constraint pk_mid primary key (mid) ,constraint uk_email unique (email));

范例:将mid和name两个字段同时设置为主键
drop table member purge ;
create table member(mid number ,name varchar2(200) not null ,email varchar2(50) ,
constraint pk_mid_name primary key (mid,name) ,constraint uk_email unique(email)) ;

范例:插入正确数据
insert into member (mid,name,email) values(1,‘Tony’,‘Tony@163.com’) ;
insert into member (mid,name,email) values(1,‘Mark’,‘Mark@163.com’);
范例:插入错误的数据 —— mid和name相同
insert into member (mid,name,email) values(1,‘Tony’,‘Tony@163.com’);
错误报告 -
ORA-00001: 违反唯一约束条件 (SPORT.PK_MID_NAME)
范例:查看member表数据
select * from member ;
小结
主键约束 = 非空约束 + 唯一约束;
复合主键约束一般不建议使用,尽量避免使用

4、检查约束
检查约束指的是对数据增加的条件过滤,表中的每行数据都必须满足指
定的过滤条件。在进行数据更新操作时,如果满足检查约束所设置的
条件,数据可以成功更新,如果不满足,则不能更新,在SQL语句中
使用CHECK(简称CK)设置检查约束的条件。

检查约束 —— 范例
在member表中增加age字段(年龄范围是0~200岁)和sex字段(只能是男或女)
drop table member purge ;
create table member(mid number ,name varchar2(200) not null
,email varchar2(50) ,age number check (age between 0 and 200)
,sex varchar2(10) ,constraint pk_mid_name primary key (mid,name) ,
constraint uk_email unique (email) ,
constraint ck_sex check (sex in (‘男’,‘女’)));
select * from member;
insert into member values(1,‘asd’,‘asd@163.com’,66,‘男’);
insert into member values(1,‘asd’,‘asd@163.com’,6666,‘男’);
报错ORA-02290: 违反检查约束条件 (SCOTT.SYS_C0011363)。

小结
检查约束会设置多个过滤条件,所以检查约束过多时会影响数据更新

5、外键约束的产生分析
例如,现在公司要求每一位成员为公司发展提出一些更好的建议,并且希望将这些建议保存在数据表之中,那么根据这样的需求,可以设计出如图所示的设计模型。

设计出了两张数据表,两张表的作用如下:
人员表:用于保存成员的基本信息(编号、姓名)
建议表:保存每一个成员提出的建议内容,所以在此表之中保存在了一个成员编号,即:通过此成员编号就可以和成员表进行数据的关联
:根据给出的数据模型编写数据库创建脚本
drop table member purge ;
drop table advice purge ;
create table member (mid number ,name varchar2(200) not null ,
constraint pk_mid primary key (mid)) ;
create table advice (adid number ,content clob not null ,mid number
,constraint pk_adid primary key (adid)) ;
插入正确的数据 —— 向member表插入两个会员信息
insert into member (mid,name) values (1,‘Tony’) ;
insert into member (mid,name) values (2,‘Mark’) ;
commit ;
select * from member;
插入正确的数据 —— 向advice表插入五条新记录
insert into advice (adid,content,mid) values (1,‘应该提倡内部沟通机制,设置总裁邮箱’,1) ;
insert into advice (adid,content,mid) values (2,‘为了使公司内部良性发展,所有的部门领导应该重新应聘上岗’,1) ;
insert into advice (adid,content,mid) values (3,‘要多开展员工培训活动,让员工更加有归属感’,1) ;
insert into advice (adid,content,mid) values (4,‘应该开展多元化业务,更加满足市场需求’,2) ;
insert into advice (adid,content,mid) values (5,‘大力发展技术部门,为本公司设计自己的ERP系统,适应电子化信息发展要求’,2) ;
commit;
select * from advice;
查询出每位成员的完整信息以及所提出的意见数量
select m.mid,m.name,count(a.mid) from member m,advice a
where m.mid=a.mid group by m.mid,m.name ;
在意见表(advice)中增加以下错误的信息
insert into advice (adid,content,mid) values (6,‘岗位职责透明化’
,99) ;
select * from advice ;
修改表结构,指定主-外键约束
drop table member purge ;
drop table advice purge ;
create table member (mid number ,name varchar2(200) not null ,constraint pk_mid primary key (mid)) ;
create table advice (adid number ,content clob not null ,mid number ,constraint pk_adid primary key (adid) ,
constraint fk_ mid foreign key(mid) references member(mid);

范例:向advice表中插入错误的数据 —— 此时member表中没有mid=99的数据
insert into advice (adid,content,mid) values (6,‘岗位职责透明化’,99) ;
范例:插入正确的数据
insert into member (mid,name) values (1,‘Tony’) ;
insert into advice (adid,content,mid) values (1,‘应该提倡内部沟通机制,设置总裁邮箱’,1) ;
insert into advice (adid,content,mid) values (3,‘要多开展员工培训活动,让员工更加有归属感’,2) ;
commit ;

级联操作 删除数据 rollback可以恢复?
级联操作
问题一:删除父表数据前需要先清出所有子表的对应数据【级联操作一】级联删除(ON DELETE CASCADE)【级联操作二】级联设置NULL(ON DELETE SET NULL)
问题二:删除父表时需要先将子表删除

范例:删除member表中编号为“1”的数据(mid=1),此时没有删除子表(advice)数据
delete from member where mid=1 ;
范例:先删除子表(advice)中mid=1的数据,之后再删除父表(member)中mid=1的数据
delete from advice where mid=1 ;
delete from member where mid=1 ;
commit ;
范例:查询member表中的记录
SELECT * FROM member

范例:修改表创建语法,增加级联删除,同时配置测试数据
drop table advice purge ;
drop table member purge ;
create table member (mid number ,name varchar2(200) not null ,
constraint pk_mid primary key (mid)) ;
create table advice (adid number ,content clob not null ,mid number ,
constraint pk_adid primary key (adid) ,
constraint fk_mid foreign key(mid) references member(mid) on delete cascade);

insert into member (mid,name) values (1,‘Tony’) ;
insert into member (mid,name) values (2,‘Mark’) ;
insert into advice (adid,content,mid) values (1,
‘应该提倡内部沟通机制,设置总裁邮箱’,1) ;
insert into advice (adid,content,mid) values (3,
‘要多开展员工培训活动,让员工更加有归属感’,2) ;
commit;
范例:查询member表中的当前数据
select * from member ;
范例:查询advice表中的当前数据
select * from advice ;
范例:删除member表中编号为1的成员信息
delete from member where mid=1 ;
范例:查询member表记录
select * from member ;
范例:查询advice表记录
select * from advice;

范例:修改表的创建语句,增加on delete set null子句
drop table advice purge ;
drop table member purge ;
create table member (mid number ,name varchar2(200) not null ,
constraint pk_mid primary key (mid)) ;
create table advice (adid number ,content clob not null ,mid number ,
constraint pk_adid primary key (adid) ,
constraint fk_mid foreign key(mid) references member(mid) on delete set null);

范例:修改表的创建语句,增加on delete set null子句
insert into member (mid,name) values (1,‘Tony’) ;
insert into member (mid,name) values (2,‘Mark’) ;
insert into advice (adid,content,mid) values (1,‘应该提倡内部沟通机制,设置总裁邮箱’,1) ;
insert into advice (adid,content,mid) values (3,‘要多开展员工培训活动,让员工更加有归属感’,2) ;
commit ;

范例:查询member表中的当前数据
select * from member ;
范例:查询advice表中的当前数据
select * from advice ;
范例:删除member表中编号为1的成员信息
delete from member where mid=1 ;
范例:查询member表记录
select * from member ;
范例:查询advice表记录
select * from advice;

主外键表的删除操作

范例:直接删除父表(member)
drop table member ;
错误报告 -
ORA-02449: 表中的唯一/主键被外键引用
范例:先删除子表(advice),再删除父表(member)。
drop table advice purge ;
drop table member purge ;
范例:强制性删除member表
drop table member cascade constraint;

小结
级联操作

on delete cascade、on delete set null;

使用外键约束后删除表时应先删除子表再删除父

查看约束 —— 范例

查看全部的约束名称、类型、约束设置对应的表名称
select constraint_name,constraint_type,table_name from user_constraints;
在这里插入图片描述

查询emp表上的全部约束
SELECT constraint_name,constraint_type,table_name FROM user_constraints WHERE table_name=‘EMP’;
在这里插入图片描述
查询user_cons_columns数据字典
select * from user_cons_columns;
在这里插入图片描述
小结
约束依然属于数据库对象,可以直接利用数据字典查。

增加约束
为表中增加约束语法:

alter table 表名称 add constraint 约束名称 primary key(约束字段) ;
范例:为member表的mid字段增加主键约束
alter table member add constraint pk_mid primary key(mid) ;
范例:为member表的age增加检查约束
alter table member add constraint ck_age check(age between 0 and 200);
在这里插入图片描述

范例:假设有如下的一张表
drop table member purge ;
create table member(mid number ,name varchar2(30) ,age number) ;
范例:查看member表中的约束
select constraint_name,constraint_type,table_name from user_constraints
where table_name=‘MEMBER’ ;
范例:为member表的mid字段增加主键约束
alter table member add constraint pk_mid primary key(mid) ;
范例:为member表的age增加检查约束
alter table member add constraint ck_age check(age between 0 and 200) ;
为表中添加完约束之后,下面可以通过数据字典user_constraints查看member表中的全部约束。
范例:查看member表中的约束
select constraint_name,constraint_type,table_name from user_constraints where table_name=‘MEMBER’ ;

范例:为name字段设置非空约束
alter table member modify (name varchar2(30) not null);
在这里插入图片描述
在这里插入图片描述

启用/禁用约束
启用/禁用约束
禁用约束
ALTER TABLE 表名称 DISABLE CONSTRAINT 约束名称 [CASCADE];
范例:禁用advice表中的adid主键约束“pk_adid”
ALTER TABLE advice DISABLE CONSTRAINT pk_adid ;
启用约束
ALTER TABLE 表名称 ENABLE CONSTRAINT 约束名称 ;
范例:禁用member表中的“pk_mid”约束,此字段在advice表中是外键
ALTER TABLE member ENABLE CONSTRAINT pk_mid

范例:给出要操作的数据表
drop table advice purge ;
drop table member purge ;
create table member (mid number ,name varchar2(200) not null ,
constraint pk_mid primary key (mid)) ;
create table advice (adid number ,content clob not null ,mid number ,
constraint pk_adid primary key (adid) ,
constraint fk_mid foreign key(mid) references member(mid) on delete set null);
insert into member (mid,name) values (1,‘Tony’) ;
insert into member (mid,name) values (2,‘Mark’);
insert into advice (adid,content,mid) values (1,‘应该提倡内部沟通机制,设置总裁邮箱’,1) ;
insert into advice (adid,content,mid) values (2,‘为了使公司内部良性发展,所有的部门领导应该重新应聘上岗’,1) ;
insert into advice (adid,content,mid) values (3,‘要多开展员工培训活动,让员工更加有归属感’,1) ;
insert into advice (adid,content,mid) values (4,‘应该开展多元化业务,更加满足市场需求’,2) ;
insert into advice (adid,content,mid) values (5,‘大力发展技术部门,为本公司设计自己的ERP系统,适应电子化信息发展要求’,2) ;
commit;
范例:禁用advice表中的adid主键约束“pk_adid”
alter table advice disable constraint pk_adid;
范例:查询禁用约束之后advice表中的数据
select * from advice ;
范例:禁用member表中的“pk_mid”约束,此字段在advice表中是外键
alter table member disable constraint pk_mid cascade;
范例:增加两条mid相同的数据
insert into member(mid,name) values (1,‘Tom’) ;
insert into member(mid,name) values (1,‘Jack’) ;
范例:查询member表中的记录
select * from member ;
范例:重新启动member表中的主键约束“pk_mid”
alter table member enable constraint pk_mid ;
范例:重新启动advice表中的主键约束“pk_adid”
alter table advice enable constraint pk_adid;

删除约束
删除约束
ALTER TABLE 表名称 DROP CONSTRAINT 约束名称 [CASCADE];
范例:删除advice表之中的“pk_adid”约束 —— 无关联外键
ALTER TABLE advice DROP CONSTRAINT pk_adid ;
范例:删除member表之中的“pk_mid”约束 —— 有关联外键
ALTER TABLE member DROP CONSTRAINT pk_mid CASCADE;

小结
约束在建立表的时候一定要同时建立;对于约束不建议对其进行修

<think>好的,用户现在想了解SQL完整性约束。之前他们已经问过多表联合查询,现在转向数据库的另一个重要概念,说明他们可能在深入学习数据库设计或优化方面的内容。首先,我需要回顾一下完整性约束的基本定义和类型,确保覆盖主要的关键点。 用户可能对完整性约束不太熟悉,所以需要从基础讲起,比如实体完整性、参照完整性、域完整性等。同时,要结合实际应用场景,这样用户更容易理解这些约束的作用。比如,实体完整性通过主键实现,确保每行数据唯一;参照完整性通过外键维护表之间的关系,防止出现无效的引用。 然后,要考虑用户可能的疑问,比如不同的约束类型如何在SQL中具体实现,可能需要示例代码。例如,创建表时如何定义主键、外键、检查约束等。还要注意用户是否了解这些约束数据库设计中的重要性,比如保证数据的一致性和准确性。 用户可能还会关心约束的命名和修改,比如如何添加或删除约束,这也是实际应用中常见的操作。需要提供相应的SQL语法示例,比如使用ALTER TABLE来添加外键约束。此外,触发器和断言虽然不常用,但作为高级内容可以简要提及,让用户有全面的了解。 还需要注意用户可能混淆的概念,比如唯一约束和主键的区别,或者检查约束与触发器的适用场景。这时候需要明确解释它们的异同,帮助用户正确选择使用哪种约束方式。 另外,考虑用户的实际操作,可能需要提醒一些注意事项,比如外键约束可能带来的性能影响,或者在插入大量数据时暂时禁用约束以提高效率。这些实战技巧对用户来说应该很有帮助。 最后,总结完整性约束的重要性,并给出学习建议,比如通过实际创建表并测试约束来加深理解。可能推荐一些在线工具或练习平台,方便用户动手实践。</think>以下是关于 **SQL完整性约束** 的详细介绍,涵盖核心概念、分类及实际应用: --- ### **一、完整性约束的核心作用** 保证数据库中数据的 **准确性**、**一致性** 和 **可靠性**,防止无效或矛盾数据进入数据库。 **类比**:类似于交通规则,约束数据的“行为规范”。 --- ### **二、约束类型与语法详解** #### **1. 实体完整性(Entity Integrity)** - **目标**:确保表中每行数据的唯一性 - **实现方式**:主键(`PRIMARY KEY`) ```sql CREATE TABLE Students ( student_id INT PRIMARY KEY, -- 约束 name VARCHAR(50) ); -- 或表级约束(联合主键) CREATE TABLE Enrollments ( student_id INT, course_id INT, PRIMARY KEY (student_id, course_id) ); ``` #### **2. 参照完整性(Referential Integrity)** - **目标**:维护表间关系的一致性 - **实现方式**:外键(`FOREIGN KEY`) ```sql CREATE TABLE Orders ( order_id INT PRIMARY KEY, customer_id INT, FOREIGN KEY (customer_id) REFERENCES Customers(customer_id) ON DELETE CASCADE -- 级联删除 ); ``` #### **3. 域完整性(Domain Integrity)** - **目标**:限定字段的取范围 - **实现方式**: - **非空约束**:`NOT NULL` ```sql CREATE TABLE Users ( username VARCHAR(20) NOT NULL ); ``` - **唯一约束**:`UNIQUE` ```sql CREATE TABLE Products ( product_code VARCHAR(10) UNIQUE ); ``` - **检查约束**:`CHECK` ```sql CREATE TABLE Employees ( age INT CHECK (age >= 18), gender CHAR(1) CHECK (gender IN ('M', 'F')) ); ``` #### **4. 用户定义完整性(自定义规则)** - **实现方式**:触发器(`TRIGGER`)或存储过程 ```sql CREATE TRIGGER salary_check BEFORE INSERT ON Employees FOR EACH ROW BEGIN IF NEW.salary < 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '薪资不能为负数'; END IF; END; ``` --- ### **三、约束操作进阶技巧** #### **1. 约束命名与修改** ```sql -- 添加命名约束 ALTER TABLE Students ADD CONSTRAINT chk_age CHECK (age BETWEEN 12 AND 25); -- 删除约束 ALTER TABLE Students DROP CONSTRAINT chk_age; ``` #### **2. 外键约束行为控制** | **操作** | **说明** | |----------------|----------------------------------| | `ON DELETE CASCADE` | 主表记录删除时,从表关联记录同步删除 | | `ON UPDATE SET NULL` | 主表主键更新时,从表外键设为 NULL | #### **3. 延迟约束检查** (适用于 PostgreSQL/Oracle) ```sql SET CONSTRAINTS ALL DEFERRED; -- 事务提交时统一检查 ``` --- ### **四、典型应用场景** 1. **电商系统** - 使用 `CHECK(quantity > 0)` 确保库存不为负 - 外键约束保证订单关联的用户必须存在 2. **金融系统** - `NOT NULL` 强制要求交易金额字段必填 - 触发器检查转账金额不超过账户余额 3. **社交平台** - `UNIQUE(email)` 防止重复注册 - `CHECK(LENGTH(password) >= 8)` 密码强度限制 --- ### **五、注意事项与优化** | **问题** | **解决方案** | |-------------------------|----------------------------------| | 过多外键影响写入性能 | 在批量导入时临时禁用约束 | | 检查约束跨表验证困难 | 改用触发器实现复杂逻辑 | | 主键选择不当导致碎片化 | 优先使用自增整型或UUID | --- ### **六、扩展知识:断言(ASSERTION)** - **作用**:跨表的全局性约束(但 MySQL 不支持) - **示例**(SQL标准语法): ```sql CREATE ASSERTION budget_limit CHECK ( NOT EXISTS ( SELECT department_id FROM Projects GROUP BY department_id HAVING SUM(budget) > 1000000 ) ); ``` --- **学习建议**: 1. 在 MySQL Workbench 或 pgAdmin 中创建带约束的表,尝试插入违反约束数据观察报错 2. 使用 `SHOW CREATE TABLE table_name;` 查看已有表的约束定义 3. 重点理解不同约束数据一致性的保护机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值