零基础学SQL
上QQ阅读APP看书,第一时间看更新

4.3 使用约束

为了保证数据的完整性,需要使用数据库约束。约束主要包括唯一约束(UNIQUE)、主键约束(PRIMARY KEY)、外键约束(FOREIGN KEY)、检查约束(CHECK)和非空约束(NOT NULL)。这一节将介绍这几种约束的作用以及它们在创建数据表的过程中是如何定义的。

4.3.1 唯一约束

唯一约束(UNIQUE)用来保证某一列或者一组列中没有相同的值。如果为列定义了唯一约束,则该列中不允许出现重复的值,但是允许列中存在空值(即NULL值)。唯一约束既可以定义的表级上,也可以定义在列级上。一般在为列创建唯一约束后,数据库会自动为该列建立一个唯一索引,其索引名与约束名是相同的。

例4.2 创建院系信息表,并为院校编号所在列定义唯一约束。

        CREATE TABLE T_dept (
        deptID   VARCHAR (15) UNIQUE,
        deptName VARCHAR (10)

在这段SQL语句中,使用CREATE TABLE语句院系信息表,并为列deptID定义唯一约束。其中, T_dept是表的名字,这里T_dept表示院系信息表。在T_dept表中,共指定了2个列用来描述院系信息。

❑deptID指定数据表的列名,列deptID表示院系编号,VARCHAR (15)用来指定deptID列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为15,UNIQUE用来指定列deptID的完整性约束条件,这里将其定义为唯一约束。

❑列deptName表示院系名称,VARCHAR (10)用来指定deptName列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为10。

选中MySQL 5.0用户图形界面的右侧Schemata选项下的test_STInfo数据库中的院系信息表T_dept,单击鼠标右键,在出现的列表中选择“Edit Tabel”选项,在出现的表编辑对话框中,选择对话框下方的“Indices”选项卡,可以看到为院系信息表T_dept中列deptID定义的唯一约束信息,如图4.4所示。

图4.4 唯一约束信息

在图4.4中,“Indices”选项卡下描述了对院系信息表T_dept中列deptID定义的唯一约束信息。在“Index Settings”选项下指定了数据表T_dept中唯一约束的信息。其中,“Index Name”指定了索引的名字,“Index Kind”指定了索引的类型为唯一索引,“Index Type”指定了索引类型;在界面的右下方空白处,在Index Columns选项下指定了唯一索引的列名为deptID。

注意 在为列创建唯一约束后,数据库会为该列建立一个唯一索引,其索引名与约束名是相同的。

4.3.2 主键约束

主键约束(PRIMARY KEY)是用来保证使用主键约束的某一列或者一组列中有唯一的值,并且不能包含空值(即NULL值)。数据表中每一列只能定义一个PRIMARY KEY。一般在为列创建主键约束后,数据库会自动为该列建立一个主索引,其索引名与约束名是相同的。

在创建数据表时,如果希望将多个列组合起来作为一个数据表中的主键,可以在PRIMARY KEY关键字后使用括号,将需要定义为主键的列放到PRIMARY KEY关键字后面的括号中。括号中的多个列之间需要使用逗号分隔。

例4.3 创建成绩信息表。

        CREATE TABLE T_result(
        stuID VARCHAR (15) ,
        curID VARCHAR (15) ,
        result DOUBLE ,
        PRIMARY KEY (stuID,curID)
        )

在这段SQL语句中,使用CREATE TABLE语句成绩信息表,并将列stuID和列curID联合作为主键。其中,T_result是表的名字,这里T_result表示成绩信息表。在T_result表中,共指定了3个列用来描述学生的成绩信息。

❑stuID指定数据表的列名,列stuID表示学生编号,VARCHAR (15)用来指定stuID列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为15。

❑curID指定数据表的列名,列curID表示院系编号,VARCHAR (15)用来指定curID列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为15。

❑列result表示学生成绩,DOUBLE用来指定result列的数据类型,这里将其定义为DOUBLE类型的数据。

❑PRIMARY KEY表示主键约束,这里将列stuID和列curID联合作为成绩信息表的主键。

选中MySQL 5.0用户图形界面的右侧Schemata选项下test_stinfo数据库中的成绩信息表T_result,单击鼠标右键,在出现的列表中选择“Edit Tabel”选项,在出现的表编辑对话框中,选择对话框下方的“Indices”选项卡,可以看到为成绩信息表T_result中列stuID和列curID定义的主键约束信息,如图4.5所示。

图4.5 主键约束信息

在图4.5中,在表编辑对话框的上方,从“Columns and Indices”选项卡下的表格中可以看到列stuID和列curID前面都有一个的图标,图标表示列stuID和列curID为成绩信息表T_result的主键列。

“Indices”选项卡下方描述了对成绩信息表T_result中列stuID和列curID定义的主键约束信息。其中,在表编辑对话框的左下方的空白处有一个PRIMARY关键字,在界面的右下方空白处,在Index Columns选项下指定了PRIMARY关键字对应的主键为列stuID和列curID。

注意 在为列创建主键约束后,数据库会为该列建立一个主索引,其索引名与约束名是相同的。

4.3.3 外键约束

首先来考虑这样一个问题,现在由于某种原因需要将一名学生在学校的全部信息删除。这里涉及学生信息的一共有两个表,一个是学生信息表,一个是成绩信息表。学生信息表保存的是学生的基本信息,成绩信息表保存的是学生选课的课程成绩信息。如果没有定义外键约束,将该名学生从学生信息表中删除时,而没有将该名学生的选课的课程成绩信息删除,这样就会造成两个关联表之间数据的不一致。

同样的问题也可能出现在对两个关联表中数据的修改操作中。如果是多个表之间存在关联关系的话,不定义外键约束,类似上面的情况很可能会发生。为了避免由于操作不当而引起的关联表中数据的不一致,有必要为关联表之间定义外键约束。

外键约束(FOREIGN KEY)主要是用来定义两个表之间的关系。外键约束保证了表的参照完整性,确保对一个表的数据操作不会对与之关联的表造成不利的影响。定义外键的语法格式如下:

        FOREIGN KEY[表名1](列名1) REFERENCES 表名2(列名2)
        [ON UPDATE [CASCADE]|[SET NULL]|[RESTRICT]]
        [ON DELETE[CASCADE]|[SET NULL]|[RESTRICT]]

其中,FOREIGN KEY是定义外键的关键字;表名1表示从表的名字,它是可选的;列名1指定数据表中用于外键约束条件的外键;REFERENCES关键字用来指定主表中的表名和主表中的关键列;表名2表示主表的名字;列名2表示主表中与从表列名1对应的主键列的名字;其后的ON UPDATE和ON DELETE分别指明了在对表中的数据做修改和删除时,主从表之间所要采取的主要的操作方式,它们是可选的。下面以删除操作为列,分别讲解一下这3种操作方式。

❑CASCADE:级联删除。如果主表中的一条数据记录被删除,那么从表中与之相对应的数据也将被一起删除。

❑SET NULL:置空删除。如果主表中的一条数据记录被删除,那么从表中与之相对应的数据也将被设置为空值。

❑RESTRICT:受限删除。如果主表中的一条数据记录被删除,则在执行DELETE命令时数据库管理系统会报错,通知用户与主表相对应的该数据在从表中仍然存在,但是与主表相对应的该数据在从表中不会被删除。它是默认的方式。

例4.4 为成绩信息表定义外键。

        CREATE TABLE T_result(
        stuID   VARCHAR (15) ,
        curID   VARCHAR (15) ,
        result   DOUBLE ,
        FOREIGN KEY(stuID) REFERENCES T_student(stuID) ON DELETE CASCADE,
        PRIMARY KEY (stuID,curID)
        )

这段SQL语句在例4.3的基础上,增加了一个创建外键的语句FOREIGN KEY(stuID) REFERENCES T_student(stuID)。其中,FOREIGN KEY表示创建外键约束的关键字;stuID表示为成绩信息表(T_result)中的表示学生编号的列stuID定义外键约束;REFERENCES T_student(stuID)表示将列stuID定义为一个指向学生信息表T_student的主键stuID中的外键,并使用ON DELETE CASCADE定义了其删除方式为级联删除。

选中MySQL 5.0用户图形界面的右侧Schemata选项下的test_STInfo数据库中的成绩信息表T_result,单击鼠标右键,在出现的列表中选择“Edit Tabel”选项,在出现的表编辑对话框中,选择对话框下方的“Foreign Keys”选项卡,可以看到为成绩信息表T_result中列stuID定义的外键约束信息,如图4.6所示。

图4.6 外键约束

在图4.6中,“Foreign Key Settings”选项下描述了对数据表T_result中列stuID定义的外键约束信息。其中,“Key Name”表示主键的名字;“Ref.Table”指定了表T_result对应的主表,这里表T_result对应的主表为T_student(学生信息表);On Delete指定了数据删除方式,这里的删除方式指定为Cascade(级联删除);On Update指定了数据修改方式,这里的修改方式默认指定为Restrict(受限修改)。

注意 在定义外键约束时,其默认的修改和删除方式都是RESTRICT。由于例4.4的SQL语句指定了列stuID的删除方式为CASCADE(级联删除),而没有指定列stuID的修改方式,因此,数据库中就使用其默认的修改方式RESTRICT。

下面请读者思考一下,如果想在列curID中也定义一个指向课程信息表T_curriculum的主键curID中的外键约束,并将其删除方式定义为级联删除,那么上述的SQL语句应该如何完成呢?

4.3.4 检查约束

检查约束(CHECK)是用来限制列的取值范围或者取值条件,使用CHECK约束可以保证数据规则的一致性。可以为一个列定义多个CHECK约束,当为列定义了CHECK约束后,该列中所对应的数据必须满足指定的约束条件。

例4.5 定义课程信息表。

        CREATE TABLE T_curriculum(
        curID VARCHAR (15) PRIMARY KEY,
        curName VARCHAR (10),
        credit INT,
        CHECK(credit BETWEEN 3 AND 8)
        )

在这段SQL语句中,使用CREATE TABLE语句创建课程信息表,并使用CHECK关键字对列credit的取值范围进行约束。其中,T_curriculum是表的名字,这里T_curriculum表示课程信息表。在T_curriculum表中,共指定了3个列用来描述课程信息。

❑curID指定数据表的列名,列curID表示院系编号,VARCHAR (15)用来指定curID列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为15。并使用PRIMARY KEY关键字将该列定义为主键列。

❑curName指定数据表的列名,列curName表示课程的名字,VARCHAR (10)用来指定curName列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为10。

❑列credit表示课程学分,INT用来指定credit列的数据类型,这里将课程学分所在的列定义为整型类型的数据。

❑使用CHECK关键字对表示课程学分的列credit的取值范围进行约束。这里将课程学分的取值范围设置在3到8之间。如果插入的数据小于3或者大于8,则SQL语句执行时会显示错误的信息。

4.3.5 非空约束

非空约束(NOT NULL)是用来保证在向该列插入数据时不允许插入空值(即NULL值)。非空约束只能用来约束列。

例4.6 创建教师信息表。

        CREATE TABLE T_teacher (
        teaID   VARCHAR (15) PRIMARY KEY,
        teaName VARCHAR (10)   NOT NULL,
        age   INT   NOT NULL,
        sex   VARCHAR (2) NOT NULL,
        deptID VARCHAR (15),
        dept VARCHAR (20)   NOT NULL,
        profession VARCHAR (10)
        )

这段SQL语句是使用CREATE TABLE创建一张教师信息表。其中,T_teacher表示创建数据表的表名,在T_teacher表中,共指定了7个列用来描述教师信息。

❑teaID指定数据表的列名,列teaID用来表示教师编号;VARCHAR (15)用来指定teaID列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为15;PRIMARY KEY用来指定列teaID的完整性约束条件,这里将列teaID设定为主键,表示列teaID的值唯一并且不能为空值(NULL值)。

❑teaName指定数据表的列名,列teaName用来表示教师姓名;VARCHAR (10)用来指定teaName列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为10;NOT NULL用来指定列teaName的完整性约束条件,这里将列teaName设定为非空,表示该列中不允许存在空值(NULL值)。

❑age指定数据表的列名,列age用来表示教师年龄;INT用来指定age列的数据类型,这里将其指定为INT类型,表示教师的年龄存储在数据库中都应该是整数;NOT NULL用来指定列age的完整性约束条件,这里将列age设定为非空,表示该列中不允许存在空值(NULL值)。

❑sex指定数据表的列名,列sex用来表示教师性别;VARCHAR (2)用来指定sex列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为2;NOT NULL用来指定列sex的完整性约束条件,这里将列sex设定为非空,表示该列中不允许存在空值(NULL值)。

❑deptID指定数据表的列名,列deptID用来表示教师所在的院系编号;VARCHAR (15)用来指定deptID列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为15。

❑dept指定数据表的列名,列dept用来表示教师所在的院系;VARCHAR (20)用来指定dept列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为20;NOT NULL用来指定列dept的完整性约束条件,这里将列dept设定为非空,表示该列中不允许存在空值(NULL值)。

❑profession指定数据表的列名,列profession用来表示教师的职称;VARCHAR (10)用来指定profession列的数据类型,这里将其指定为VARCHAR类型,并且设定该列中字符串长度为10。

在创建的教师信息表(T_teacher)中,表示教师姓名的列teaName、表示教师年龄的列age、表示教师性别的列sex和表示教师所在院系的列dept都定义为NOT NULL类型的,也就是这几个列在数据插入时不允许插入空值。