第4章 约束与规则

第4章 约束与规则

在关系型数据库中确保数据完整性的主要手段就是数据表中约束的设置。约束是对数据表中输入数据的限制,合理的使用约束会在实际应用中起到事半功倍的效果。
约束在标准SQL中主要分为主键约束、外键约束、唯一约束、非空约束、检查约束5种约束。其中,主键约束和唯一约束的作用都是确保设置该约束的列输入值的唯一性;外键约束是在5个约束中唯一一个涉及2张表的约束。

4.1 主键约束—PRIMARY KEY
主键约束在每张数据表中只有一个,但是一个主键约束可以由1到多个列来组成。由多个列组成的主键约束,也称为联合主键。设置了主键约束的列就确保了该列数据值的唯一性,即不允许输入重复的数据。主键约束的关键字是PRIMARY KEY,因此在设置主键约束时也经常把主键约束的名字以PK开头。

4.1.1 在创建表时设置单一列的主键约束
在设计数据表时为了避免两行记录完全一致,经常要使用主键约束对某一列加以约束。设置主键的列通常是一个表中的编号列。
【语法说明】
在创建表时设置单一列的主键约束方法有2种,语法如下所示。
(1)设置列级主键约束

CREATE TABLE_NAME table_name
(
COLUMN_NAME1  DATATYPE PRIMARY KEY,
COLUMN_NAME2  DATATYPE,
COLUMN_NAME3  DATATYPE
  ……
)

(2)设置表级主键约束

CREATE TABLE_NAME table_name
(
COLUMN_NAME1  DATATYPE,
COLUMN_NAME2  DATATYPE,
COLUMN_NAME3  DATATYPE
……
[CONSTRAINT constraint_name] PRIMARY KEY(COLUMN_NAME1)
)

这里,[CONSTRAINT constraint_name]是可以省略的。

说明:在上述2种语法中都是将COLUMN_NAME1列设置成了主键约束。第1种创建主键约束的语法是在设置单一列主键约束中比较常用的方法。

【上机实战】
分别用上面的2种方法,创建酒店管理系统中的客户信息表并给客户编号设置成主键。表结构如表4.1所示。
表4.1 客户信息表(CustomerInfo)

编号   列名	   数据类型	  中文释义
1	CustomerId	INTEGER	客户编号
2	CustomerName	VARHCAR(12)	客户姓名
3	CustomerAge	INTEGER	客户年龄
4	CustomerSex	VARCHAR(4)	客户性别
5	CustomerTel	VARCHAR(15)	客户联系方式
6	Remark	VARCHAR(200)	备注

使用第1种语法创建客户信息表,并给客户编号列CustomerId设置成主键约束,代码如下所示。

CREATE TABLE CUSTOMERINFO
(
   CUSTOMERID INTEGER PRIMARY KEY,
   CUSTOMERNAME VARCHAR(12),
   CUSTOMERAGE INTEGER,
   CUSTOMERSEX VARCHAR(4),
   CUSTOMERTEL VARCHAR(15),
   REMARK      VARCHAR(200)
)

使用第2种语法创建客户信息表,并给客户编号列CustomerId设置成主键约束,代码如下所示。

CREATE TABLE CUSTOMERINFO
(
   CUSTOMERID INTEGER,
   CUSTOMERNAME VARCHAR(12),
   CUSTOMERAGE INTEGER,
   CUSTOMERSEX VARCHAR(4),
   CUSTOMERTEL VARCHAR(15),
   REMARK      VARCHAR(200),
   PRIMARY KEY(CUSTOMERID)
)

运行后的效果如图4.1所示。
在这里插入图片描述
图4.1 CUSOMERINFO表的效果

注意。在SQL Server或Oracle数据库中整型INTEGER类型可以直接写成INT类型。查询在数据表中已经创建的约束,在Oracle数据库中也可以通过数据字典user_constraints来查询;在SQL
Server数据库中可以通过存储过程sp_helpconstraints来查询。

4.1.2 在创建表时设置联合主键
所谓联合主键,就是这个主键是由一张表中的多个列组成的。在数据库表的设计时联合主键的应用是比较多的,比如,设计学生选课表,是用学生编号做主键还是用课程编号做主键呢?如果用学生编号做主键,那么一个学生就只能选择一门课程;如果用课程编号做主键,那么一门课程只能有一个学生来选。显然,这两种情况都是不符合实际情况的。实际上设计学生选课表,要限定的是一个学生只能选择同一课程一次。因此,学生编号和课程编号可以放在一起共同作为主键,这也就是联合主键了。
【语法说明】
在创建表时设置联合主键的语法如下所示。

CREATE TABLE_NAME table_name
(
COLUMN_NAME1  DATATYPE,
COLUMN_NAME2  DATATYPE,
COLUMN_NAME3  DATATYPE
……
[CONSTRAINT constraint_name] PRIMARY KEY(COLUMN_NAME1, COLUMN_NAME2,…)
)

当主键是由多个列组成时,不能直接在列名后面声明主键约束,如下面的代码所示。

CREATE TABLE_NAME table_name
(
COLUMN_NAME1  DATATYPE PRIMARY KEY,
COLUMN_NAME2  DATATYPE PRIMARY KEY,
COLUMN_NAME3  DATATYPE
)

【上机实战】
用上面的语法创建酒店管理系统中的客户订房表并给客户编号和房间号设置成联合主键,表结构如表4.2所示。
表4.2 客户订房表(OrderInfo)

编号	列名	数据类型	中文释义
1	CustomerId	INTEGER	客户编号
2	RoomId	INTEGER	房间编号
3	CheckInDate	DATETIME	入住时间
4	CheckOutDate	DATETIME	退房时间
5	Amount	NUMERIC(7,2)	付款金额
6	Remark	VARCHAR(200)	备注

创建客户信息表(OrderInfo)并设置联合主键的代码如下所示。

CREATE TABLE ORDERINFO
(
  CUSTOMERID INTEGER,
  ORDERID    INTEGER,
  CHECKINDATE DATETIME,
  CHECKOUTDATE DATETIME,
  AMOUNT     NUMERIC(7,2),
  REMARK     VARCHAR(200),
  PRIMARY KEY(CUSTOMERID,ORDERID)
)

运行后的效果如图4.2所示。
在这里插入图片描述
图4.2 ORDERINFO表的效果
从图4.2中可以看出,CUSTOMERID和ORDERID前面都有一个小钥匙,这就是联合主键的设置效果。

4.1.3 在修改表时添加单一列的主键约束
主键约束不仅可以在创建表的同时创建,也可以在修改数据表时添加。设置成主键约束的列中不允许有空值。
【语法说明】
当数据表已经存在的前提下,要给表中的单一列添加主键约束,具体的语法如下所示。

ALTER TABLE table_name
ADD CONSTRAINT pk_name PRIMARY KEY(列名)

【上机实战】
假设在数据库里已经存在酒店管理系统中的客房信息表(RoomInfo),表结构如表4.3所示。
表4.3 客房信息表(RoomInfo)

编号	列名	数据类型	中文释义
1	RoomId	INTEGER	房间编号
2	RoomTypeId	INTEGER	房间类型编号
3	RoomPrice	NUMERIC(7,2)	房间价格
4	RoomState	VARCHAR(2)	房间状态
5	Remark	VARCHAR(200)	备注

给客房信息表(RoomInfo)中的RoomId列添加主键约束,代码如下所示。

ALTER TABLE ROOMINFO
ADD CONSTRAINT PK_ROOMINFO PRIAMRY KEY(ROOMID)

运行后的效果如图4.3所示。
在这里插入图片描述
图4.3 给列ROOMID添加主键约束前后的对比图

说明:在为设计好的表的中添加主键约束时,要确保添加主键约束的列是非空的,否则就会出现如图4-4所示的错误消息。

图4.4 错误消息
在这里插入图片描述

4.1.4 在修改表时添加联合主键
在修改数据表时,除了可以为表添加单一列的主键约束外,也可以为表添加联合主键。
【语法说明】
在修改表时添加联合主键约束的语法如下所示。

ALTER TABLE table_name
ADD CONSTRAINT pk_name PRIMARY KEY(列名1,列名2…)

【上机实战】
假设订房信息表(OrderInfo)如表4.2已经存在,但是并没有创建主键。现在要将OrderInfo表中的CustomerId和RoomId两列设置成主键。创建的语法如下所示。

ALTER TABLE ORDERINFO
ADD CONSTRAINT PK_ORDERINFO PRIMARY KEY(CUSTOMERID,ROOMID)

运行后的效果如图4.5所示。
在这里插入图片描述
图4.5 添加联合主键的效果

4.1.5 删除主键约束
当一个表中不需要主键约束时,就需要从表中将其删除。删除主键约束的方法要比创建主键约束容易得多。
【语法说明】
删除主键约束的语法如下所示。

ALTER TABLE table_name
DROP CONSTRAINT pk_name

pk_name是表中要删除的主键约束名称。
【上机实战】
删除客户信息表(CUSTOMERINFO)中的主键约束PK_ CUSTOMERINFO,代码如下所示。

ALTER TABLE CUSTOMERINFO
DROP CONSTRAINT PK_ CUSTOMERINFO

执行效果就是把CUSTOMERINFO表中CUSTOMERID旁边的小钥匙去掉,如图4.6所示。
在这里插入图片描述
图4.6 删除主键约束前后对比效果

4.2 唯一约束—UNIQUE
唯一约束与主键约束有一个相似的地方就是它们都是确保列的唯一性的。与主键约束不同的是唯一约束在一个表中可有多个,并且设置唯一约束的列是允许有空值的,但是只能有一个空值。比如,在用户信息表中,要避免表中的用户名重名,就可以把用户名列设置上唯一约束。

4.2.1 在创建表时设置一列的唯一约束
唯一约束可以在创建表时直接在表设置。唯一约束通常设置在除了主键以外的其他列上,比如,在客户信息表中可以把客户的电话号码设置成唯一约束。
【语法说明】
在创建表时添加唯一约束的语法可以有2种形式。下面的两个语法都是将表中的COLUMN_NAME2列设置成唯一约束。如下所示。
(1)列级唯一约束的设置

CREATE TABLE table_name
( 
COLUMN_NAME1 DATETYPE,
COLUMN_NAME2 DATETYPE UNIQUE,
COLUMN_NAME3 DATETYPE
)

(2)表级唯一约束的设置

CREATE TABLE table_name
( 
COLUMN_NAME1 DATETYPE,
COLUMN_NAME2 DATETYPE,
COLUMN_NAME3 DATETYPE,
[CONSTRAINT constraint_name] UNIQUE(COLUMN_NAME2)
)

这里,[CONSTRAINT constraint_name]是可以省略的。
【上机实战】
分别使用上面2种语法创建唯一约束。在创建客户信息表(CUSTOMERINFO)时,为客户姓名(CUSTOMERNAME)列设置上唯一约束。
使用第1种方法,代码如下所示。

CREATE TABLE CUSTOMERINFO
(
CUSTOMERID  INTEGER PRIMARY KEY,
CUSTOMERNAME VARCHAR(12) UNIQUE,
CUSTOMERAGE INTEGER,
CUSTOMERSEX VARCHAR(4),
CUSTOMERTEL VARCHAR(15),
REMARK      VARCHAR(200)
)

使用第2种方法,代码如下所示。

CREATE TABLE CUSTOMERINFO
(
CUSTOMERID   INTEGER PRIMARY KEY,
CUSTOMERNAME VARCHAR(12),
CUSTOMERAGE INTEGER,
CUSTOMERSEX VARCHAR(4),
CUSTOMERTEL VARCHAR(15),
REMARK      VARCHAR(200),
UNIQUE(CUSTOMERNAME)
)

执行上面的代码,效果如图4.7所示。
在这里插入图片描述
图4.7 CUSTOMERINFO表中添加的唯一约束

4.2.2 在创建表时为多个列设置唯一约束
唯一约束与主键约束重要的区别就在于唯一约束可以在一个表中多个列中设置,并且在设置时系统会自动生成不同的约束名称。
【语法说明】
为表中多列设置唯一约束的语法形式也有2种,如下所示。
(1)列级唯一约束

CREATE TABLE table_name
( 
COLUMN_NAME1 DATETYPE UNIQUE,
COLUMN_NAME2 DATETYPE UNIQUE,
COLUMN_NAME3 DATETYPE
)

(2)表级唯一约束

CREATE TABLE table_name
( 
COLUMN_NAME1 DATETYPE,
COLUMN_NAME2 DATETYPE,
COLUMN_NAME3 DATETYPE,
[CONSTRAINT constraint_name] UNIQUE(COLUMN_NAME1),
[CONSTRAINT constraint_name] UNIQUE(COLUMN_NAME2)
)

这里,[CONSTRAINT constraint_name]是可以省略的。两种形式的语法中显示的是为COLUMN_NAME1和COLUMN_NAME2分别设置唯一约束。
【上机实战】
分别使用上面的2种语法形式,在创建客户信息表(CUSTOMERINFO)的同时为客户姓名(CUSTOMERNAME)和客户年龄(CUSTOMERAGE)列分别设置唯一约束。
使用第1种方法,代码如下所示。

CREATE TABLE CUSTOMERINFO
(
   CUSTOMERID  INTEGER PRIMARY KEY,
   CUSTOMERNAME VARCHAR(12) UNIQUE,
   CUSTOMERAGE INTEGER UNIQUE,
   CUSTOMERSEX VARCHAR(4),
   CUSTOMERTEL VARCHAR(15),
   REMARK      VARCHAR(200)  
)

使用第2种方法,代码如下所示。

CREATE TABLE CUSTOMERINFO
(
   CUSTOMERID  INTEGER PRIMARY KEY,
   CUSTOMERNAME VARCHAR(12),
   CUSTOMERAGE INTEGER,
   CUSTOMERSEX VARCHAR(4),
   CUSTOMERTEL VARCHAR(15),
   REMARK      VARCHAR(200),
   UNIQUE(CUSTOMERNAME),
UNIQUE(CUSTOMERAGE)
)

执行上面的语句后,就为CUSTOMERINFO表添加了两个唯一约束。
4.2.3 在创建表时为多个列设置共同的唯一约束
唯一约束也可以向设置联合主键一样,把多个列放在一起设置。设置这种多列的唯一约束的作用是确保某几个列中的数据不重复,比如,在用户信息表中,要确保用户的登录名和密码是不重复的,就可以把登录名和密码设置成一个唯一约束。
【语法说明】
在创建表时为多个列设置共同的唯一约束,语法如下所示。

CREATE TABLE table_name
( 
COLUMN_NAME1 DATETYPE,
COLUMN_NAME2 DATETYPE,
COLUMN_NAME3 DATETYPE,
[CONSTRAINT constraint_name] UNIQUE(COLUMN_NAME1, COLUMN_NAME2,…)
)

这里,[CONSTRAINT constraint_name]是可以省略的。UNIQUE(COLUMN_NAME1, COLUMN_NAME2,…)中的COLUMN_NAME1和COLUMN_NAME2就是要设置共同唯一约束的列。
【上机实战】
使用上面的语法,在创建客户信息表(CUSTOMERINFO)时,为客户姓名(CUSTOMERNAME)和客户年龄(CUSTOMERAGE)列设置共同的唯一约束,代码如下所示。

CREATE TABLE CUSTOMERINFO
(
   CUSTOMERID  INTEGER PRIMARY KEY,
   CUSTOMERNAME VARCHAR(12),
   CUSTOMERAGE INTEGER,
   CUSTOMERSEX VARCHAR(4),
   CUSTOMERTEL VARCHAR(15),
   REMARK      VARCHAR(200),
UNIQUE(CUSTOMERNAME,CUSTOMERAGE)
)

执行上面的语句后,就为CUSTOMERINFO表添加了一个由CUSTOMERNAME和CUSTOMERAGE列组成的唯一约束。

4.2.4 在修改表时添加一个列的唯一约束
当完成表的设计后,也可以通过修改表来添加唯一约束。
【语法说明】
当数据表已经存在的前提下,要给表中的一列添加唯一约束,具体的语法如下所示。

ALTER TABLE table_name
ADD CONSTRAINT UQ_name UNIQUE(列名)

【上机实战】
给客户信息表(CUSTOMERINFO)中的客户联系方式(CUSTOMERTEL)列加上唯一约束,代码如下所示。

ALTER TABLE CUSTOMERINFO
ADD CONSTRAINT UQ_CUSTOMERINFO UNIQUE(CUSTOMERTEL)

执行上面的语句后,CUSTOMERINFO中就增加了一个唯一约束。

4.2.5 在修改表时添加多个列的共同唯一约束
为多个列添加共同的唯一约束也是经常会碰到的情况,在添加这种多列共同约束时,一定要注意这些列里的数据是否有重复的。如果有重复数据或多个空数据,就会使约束添加失败。
【语法说明】
当数据表已经存在的前提下,添加多个列的共同约束具体的语法如下所示。

ALTER TABLE table_name
ADD CONSTRAINT UQ_name UNIQUE(列名1,列名2…)

【上机实战】
给客户信息表(CUSTOMERINFO)中的客户联系方式(CUSTOMERTEL)列和客户姓名(CUSTOMERNAME)列都加上唯一约束,代码如下所示。

ALTER TABLE CUSTOMERINFO
ADD CONSTRAINT UQ_CUSTOMERINFO1 UNIQUE(CUSTOMERTEL, CUSTOMERNAME)

执行上面的语句后,就为CUSTOMERINFO表添加了一个由CUSTOMERTEL和CUSTOMERNAME列组成的唯一约束。

4.3外键约束—FOREIGN KEY
外键约束也称为FOREIGN KEY约束。FOREIGN KEY约束允许建立两个表间的父子关系。关系数据库准则规定子表中的FOREIGN KEY值必须作为PRIMARY KEY(或UNIQUE)值存在于父表中,这条准则称为引用完整性约束。
外键(FOREIGN KEY)是用于建立和加强两个表数据之间的连接的一列或多列。当创建或修改表时可通过定义FOREIGN KEY约束来创建外键。在外键引用中,当一个表的列被引用作为另一个表的主键值的列时,就在两表之间创建了连接。这个列就成为第二个表的外键。
系统保证从表在外部键上的取值要么是主表中某一个主键值或唯一键值,要么取空值,以此保证两个表之间的连接,确保了实体的参照完整性。
【语法说明】
FOREIGN KEY既可用于列约束,也可用于表约束,其语法格式为。

[CONSTRAINT <约束名>] FOREIGN KEY  REFERENCES <父表名> (<列名>[{<列名>}])

【上机实战】
创建一个记录员工薪水信息的薪水表,其表名为EmpSal,包含Salary_ID、Salary和Bank_Account三列信息,并通过定义表约束的方法为Salary_ID列创建外键约束,使其与实例1中创建的职工信息表Employees的EMP_ID列相关联。
EmpSal表为子表,它以Employees表为父表,通过定义外键约束,保证EmpSal表在外部键(Salary_ID)上的取值要么是父表中某一个主键(EMP_ID),要么取空值,以此保证两个表之间的连接,确保了实体的参照完整性。
实例创建代码如下:

USE Library
CREATE TABLE 	EmpSal
(Salary_ID  	INT,
Salary			decimal(5,1),
Bank_Account	CHAR(8)
--外键约束
CONSTRAINT  SalFK FOREIGN KEY (Salary_ID) REFERENCES Employees  (EMP_ID))

运行该代码,即创建了EmpSal表,并为表中的Salary_ID列添加了FOREIGN KEY约束。这样,Salary_ID列的取值只能是Employees表中EMP_ID列的值,或是空值。
因此,可以向EmpSal表中添加如下数据:

USE Library
INSERT INTO EmpSal
VALUES (101,2345.5,'11000234')
INSERT INTO EmpSal
VALUES (null,1768,'21345567')
SELECT * FROM EmpSal

此时,EmpSal表中的数据如图4.8所示。
在这里插入图片描述
图4.8 EmpSal表中的数据
而如果向表中添加的Salary_ID列的数据在Employees表的EMP_ID列(由图10.1可知,该列包含的数据值为101、102)中不存在,代码如下:

USE Library
INSERT INTO EmpSal
VALUES (103,1345.5,'11230234')

则系统会提示插入数据操作失败,给出如下的错误提示信息:
消息 547,级别 16,状态 0,第 2 行

The INSERT statement conflicted with the FOREIGN KEY constraint
“SalFK”. The conflict occurred in database “Library”, table
“dbo.Employees”, column ‘EMP_ID’. The statement has been terminated.

FOREIGN KEY约束并不仅仅可以与另一个表的PRIMARY KEY约束相连接,它还可以定义为引用另一个表的UNIQUE约束。FOREIGN KEY约束可以包含空值,但是,如果任何组合FOREIGN KEY约束的列包含空值,则将跳过组成FOREIGN KEY约束的所有值的验证。

4.4 非空约束
SQL中允许数据表中的列值为空值(NULL)。在创建数据表时,数据库管理系统允许通过NOT NULL关键字为创建的每列指明非空约束。因此,在添加数据时,如果该列的值为NULL,则数据库就会提示添加数据失败的错误信息。非空约束在实际应用中是十分重要的,它避免了由于用户的误操作而导致的数据信息不完整,从而保证了数据信息的完整性。

提示:如果表中的某列值为NULL,则表明该列不存在值。

【上机实战】
在创建数据表的同时为数据表中的字段添加非空约束。在创建的员工信息表(employee)表同时,为表中的员工编号(No)、员工姓名(sName)、性别(Sex)、出生日期(BirthDay)4列添加非空约束,其实现的代码如下所示。

CREATE TABLE employee
(
   No  DECIMAL(5) NOT NULL,
   sName   CHAR(10) NOT NULL,
   Sex     CHAR(2)    NOT NULL,
   BirthDay  DATETIME NOT NULL,
   Phone  CHAR(11),
   Address  CHAR(30),
   Mark  CHAR(50)
)

代码执行后,查看数据表中的结构如图4.9所示。
在这里插入图片描述
图4.9 添加约束后的employee表结构
添加约束后,可以发现被约束的员工编号(No)、员工姓名(sName)、性别(Sex)和出生日期(BirthDay)4列不允许为空,也就是说,在向数据表中添加数据时,这4列中不允许添加空数据(NULL)信息。

注意:NULL与空字符串是不同的。空字符串指的是‘’,即两个单引号中间没有任何的值,而不是指NULL。

4.5 检查约束—CHECK
CHECK(校验)约束用来检查字段值所允许的范围,比如,一个字段只能输入整数,而且限定在0~100的整数,以此来保证域的完整性。可以通过任何基于逻辑运算符(返回TRUE或FALSE)的逻辑(布尔)表达式创建CHECK约束。
【语法说明】
CHECK既可用于列约束,也可用于表约束,其语法格式如下所示。

[CONSTRAINT <约束名>] CHECK (<条件>)

可以将多个CHECK约束应用于单个列。还可以通过在表级创建CHECK约束,将一个 CHECK约束应用于多个列。
【上机实战】
创建一个学生信息表Student,其中输入性别(Sex)字段值时,只能接受“F”或者“M”,并且为Phonenum字段创建检查约束,限制只能输入类似0108079865之类的数据(前3位必须是010),而不能随意输入其他数据。创建代码如下。

USE Library
CREATE TABLE  Student
(ID int PRIMARY KEY,
Name char(8),
Sex char(2),
Phonenum char(11),
CONSTRAINT chk_sex CHECK(sex in ('F','M')),	--CHECK约束
CONSTRAINT chk_phonenum CHECK
(Phonenum like '010[0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
)

此时,DBMS将允许使用以下的INSERT语句向表中添加行:

USE Library
INSERT INTO Student VALUES (101, 'Tom', 'F',NULL)
INSERT INTO Student VALUES (102, 'John', 'M', '0108976453')
SELECT * FROM Student

得到Student表中的数据如图4.10所示。
在这里插入图片描述
图4.10 Student表中的数据
CHECK约束不接受计算结果为FALSE的值。因为空值的计算结果为UNKNOWN,所以在表达式中,如果存在NULL值,其结果就满足CHECK约束的检查。
而如果采用如下的UPDATE语句修改表中的数据。

USE Library
UPDATE Student 
SET Phonenum = '6633867'
WHERE ID = 101

系统会提示修改操作失败,给出如下的错误提示信息。
消息 547,级别 16,状态 0,第 2 行

The UPDATE statement conflicted with the CHECK constraint
“chk_phonenum”. The conflict occurred in database “Library”, table
“dbo.Student”, column ‘Phonenum’. The statement has been terminated.

这是因为修改后的数据违背了Phonenum列的CHECK约束。
当使用CHECK约束时,需要考虑以下几个因素:

  • 一个列级CHECK约束只能与限制的字段有关;一个表级CHECK约束只能与限制的表中字段有关。
  • 一个表中可以定义多个CHECK约束。
  • 每条CREATE TABLE语句中每个字段只能定义一个CHECK约束。
  • 在多个字段上定义CHECK约束,则必须将CHECK约束定义为表级约束。
  • 当执行INSERT语句或者UPDATE语句时,CHECK约束将验证数据。

CHECK约束中不能包含子查询。

4.6 删除与禁用约束
本节中我们讲解一下如何删除和禁用约束。
1.删除约束
当约束不再需要时可以将其删除。
【语法说明】
可以通过ALTER TABLE语句删除已有表的约束,其语法可表示如下。

ALTER TABLE table_name
DROP [CONSTRAINT] constraint_name

【上机实战】
删除为Student表的Phonenum字段创建的CHECK约束chk_phonenum,其实现的代码如下。

USE Library
ALTER TABLE Student
DROP CONSTRAINT chk_phonenum

执行该代码,即删除了作用在Student表上的chk_phonenum约束。而此时采用如下的UPDATE语句修改表中的数据

UPDATE Student 
SET Phonenum = '6633867'
WHERE ID = 101
SELECT * FROM Student

就能够成功执行,最终得到的Student表中的数据如图4.11所示。
在这里插入图片描述
图4.11 Student表中的数据
如果要修改一个表中的约束,则需要首先删除该约束,而后再添加新的约束。
2.禁用约束
在ALTER TABLE语句中,可以使用NOCHECK关键字禁用表中的CHECK约束和FOREIGN KEY约束。下面通过一个实例说明其具体应用。
【上机实战】
为Student表中的Sex字段通过创建CHECK约束限定其值为“F”或者“M”,因此如果采用下面的语句向表中添加数据。

USE Library
INSERT INTO Student VALUES (103, 'Mike', '男',NULL)

系统会提示与Sex字段的CHECK约束矛盾,添加数据操作失败。如果想要强行添加该数据,而又不删除约束,就可以通过使用NOCHECK关键字禁用表中的CHECK约束chk_sex,代码如下。

USE Library
ALTER TABLE Student	
NOCHECK CONSTRAINT chk_sex

此时,Student表中的chk_sex约束就不再起作用了,这时就可以通过下面的语句向表中添加数据了。

USE Library
INSERT INTO Student VALUES (103, 'Mike', '男',NULL)
SELECT * FROM Student

最终得到的Student表中的数据如图4.12所示。
在这里插入图片描述
图4.12 Student表中的数据
与删除约束不同,禁用约束只是约束不再作用于表,而约束本身仍然在数据库中存在。在需要时,还可以通过在ALTER TABLE语句中,使用CHECK关键字重新启用表中的CHECK约束和FOREIGN KEY约束。
重新启用表中的约束之前,必须确保表中的现有数据满足约束的要求。如果要重新启用Student表中的chk_sex约束,可采用下面的代码。

USE Library
UPDATE Student			--更新Student中的数据使之满足约束条件
SET Sex='M'
WHERE Sex='男'
ALTER TABLE Student		--重新启用Student中的chk_sex约束
CHECK CONSTRAINT chk_sex

此时,Student表中的chk_sex约束就重新生效。
另外,也可以通过使用ALL关键字,禁用(启用)作用在表上的所有CHECK约束和FOREIGN KEY约束。如下面的代码所示。

ALTER TABLE Student	
NOCHECK CONSTRAINT ALL

4.7 规则
规则英文名称为Rule,是指对存储在表中的列或自定义数据类型中的值的规定和限制。规则是独立的、单独存储的数据库对象,规则与其作用的表或用户自定义数据类型是相互独立、毫无关联的,也就是说,在删除表或用户自定义对象时不会对规则产生影响。
规则是独立于表的数据库对象、是实现数据完整性的方法之一。规则具有向后兼容的功能,用于执行一些与CHECK约束相同的功能。规则只能用于检查单列,不能进行同表不同列之间的比较。规则的优点是同一个规则对象可以提供给不同数据表中的不同字段使用,但字段最多只能和一个规则对象结合。一个列可以应用多个CHECK约束,但是却只能应用一个规则。
【语法说明】
使用CREATE RULE命令可以在当前数据库中创建规则。其具体的语法如下所示。

CREATE RULE rule_name AS condition

代码中的condition子句表示的是规则的定义,condition子句可以是WHERE子句中的任何表达形式,如算术运算符、关系运算符和谓词等。

注意:在condition子句中,表达式必须以“@”开头。

【上机实战】
创建员工性别的规则Sex_Rule,要求员工的性别只能输入“男”或“女”,其他任何字符都不允许输入。

CREATE RULE Sex_Rule
AS @Value= '男' OR @Value= '女'

规则创建之后,就可以应用这个规则限制输入员工的性别信息。
下面的代码演示的是,创建员工年龄的规则Age_Rule,要求员工年龄的输入范围为18-45。年龄超出这个范围的人不能视为企业的员工。

CREATE RULE Age_Rule
AS @Value BETWEEN 18 AND 45

规则创建之后,就可以应用这个规则限制输入员工的年龄信息。
下面的代码演示的是,创建员工出生日期的规则BirthDay_Rule,要求员工出生日期的范围为1970-01-01~1985-01-01。输入的出生日期不能超过这个范围。

CREATE RULE BirthDay_Rule
AS @Value BETWEEN '1970-01-01' AND '1985-01-01'

规则创建之后,就可以应用这个规则限制输入员工的出生日期信息。
下面的代码演示的是,创建限制电话号码长度的规则Phone_Rule,要求输入的电话号码的位数不允许超过11位。

CREATE RULE Phone_Rule
AS len(@Value)<11

规则创建之后,输入的电话号码长度都被限制在11位以内。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HeartBest丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值