除数据类型和大小外,表中的列还具有其他属性。数据完整性就是确保数据库中数据的一致性和正确性。数据完整性有四种类型:实体完整性、域完整性、引用完整性、用户定义完整性。SQL Server中提供了相应的组件以实现数据的完整性。其中,实体完整性将行定义为特定表的唯一实体,通过索引、UNIQUE约束、PRIMARY KEY约束等实现;域完整性是指给定列的输入有效性,强制域的方法有限制类型(通过数据类型)、格式(通过CHECK约束和规则)或可能值的范围(通过FOREIGN KEY约束、CHECK约束、DEFAULT定义、NOT NULL定义和规则);引用完整性是指在输入或删除记录时,引用完整性保持表之间已定义的关系,它主要通过FOREIGN KEY和CHECK约束来保证外键与主键之间或外键与唯一键之间的关系,确保键值在所有表中一致;用户定义完整性可以定义不属于其他任何完整性分类的特定业务规则,可以通过CREATE TABLE语句中的所有列级和表级约束、存储过程和触发器来实现。本节主要介绍约束、默认值、规则等内容。
SQL Server中提供了如下几种约束机制。
· PRIMARY KEY约束。
· FOREIGN KEY约束。
· UNIQUE约束。
· CHECK约束。
· NOT NULL(不允许空)。
以上约束是SQL Server 2000自动强制数据完整性的方式,它们定义了列中所允许值的规则,是强制完整性的标准机制,使用约束优先于其他完整性机制。下面详细介绍几种常用的约束的使用。
表中经常有一个列或列的组合,其值能唯一地标识表中的每一行,这样的一列或多列称为表的主键。当创建或更改表时可通过定义PRIMARY KEY约束(主键约束)来创建主键。一个表只能有一个PRIMARY KEY约束,而且PRIMARY KEY 约束中的列不能接受空值。所以一旦定义了PRIMARY KEY约束,其列值必定非空,必定满足NOT NULL。如果PRIMARY KEY约束定义在不止一列上,则一列中的值可以重复,但PRIMARY KEY约束定义中的所有列的组合的值必须唯一。
主键约束的创建比较简单,前面4.1节中讲述了在创建表时指定主键,4.2节中讲述了在修改表的结构时指定主键,SQL Server会自动创建一个前缀为“PK_”且后表名的主键。如果使用SQL语句来创建主键约束,则可以在列的数据类型后加上“PRIMARY KEY”关键字,从而指定该列为主键。
外键是用于建立和加强两个表数据之间的链接的一列或多列,通过将已有表中主键值的一列或多列添加到另一个表中,可创建两个表之间的链接,这个列就成为第二个表的外键。这种约束便称为FOREIGN KEY约束或者外键约束。在这个约束中,主键所在的表称为主键表,而第二个表则称为外键表。外键约束除了可以参照其他表中的列,也可以参照自身表中的其他列,这种参照称为自参照。此时主键表和外键表为同一张表。
如果建立了表的关联,系统会自动建立外键约束。而在企业管理器中若要手动建立外键约束,则可以通过关系来实施外键约束。
例如,建立class表时,teacher列要参照teacher表中tno列,则可以在class的设计窗口中右击,在弹出的快捷菜单中选择“关系”菜单项,弹出如图4-20所示对话框。
单击其中的“新建”按钮,对话框许多控件将激活,不再以灰色显示。由于该字段在teacher表中是tid列且为主键,而在class表中是teacher列为外键,则在主键表中选择“teacher”表,在外键表中选择“class”表,此时会自动给新约束命名为“FK_外键表_主键表”的格式。在本例中,该外键约束自动命名为“FK_class_teacher”,然后各自下方的列表框中选择合适的记录,即在teacher表中选择tid字段,在class表中选择teacher字段。如果在删除外键指向的行时,也删除包含指向该外键的所有行,可以单击选择“级联删除相关的记录”复选框,如果在更新外键指向的行时,也更新包含指向该外键的所有行,可以单击选择“级联更新相关的字段”复选框,如图4-21所示。设置完成后,单击“关闭”按钮退出。
图4-20 建立外键约束 图4-21 选择主键表外键表
使用UNIQUE约束可确保在非主键列中不输入重复值,即其所约束的列中,除了NULL空值外,所有的值都是不相同的。尽管UNIQUE约束和PRIMARY KEY约束都强制唯一性,但在强制下面的唯一性时应使用UNIQUE约束而不是PRIMARY KEY约束。
· 非主键的一列或列组合:一个表可以定义多个UNIQUE约束,而只能定义一个PRIMARY KEY约束。
· 允许空值的列:允许空值的列上可以定义UNIQUE约束,而不能定义PRIMARY KEY 约束。
创建了PRIMARY KEY约束后,它所约束的列必定满足UNIQUE约束。而若要在其他列上建立UNIQUE约束,可以在设计表的窗口中进行设置。
例如,若要保证每个班的班主任不相同,可以在class表中的teacher字段建立UNIQUE约束。在设计表的窗口中单击鼠标右键,在弹出的菜单中选择“索引/键”菜单项,弹出如图4-22所示对话框,默认显示的是主键约束。
单击“新建”按钮,即可建立新的索引,在“索引名”标签后的文本框中可指定新索引的名称,在其下方的列表框中选择要建立UNIQUE约束的列,在本例中选择teacher列,然后还可以选择其排列顺序,升序或者降序。
单击选择“创建UNIQUE”复选框,再单击选择“约束”单选按钮,至此已成功在class表的teacher列上建立了UNIQUE约束,如图4-23所示。
图4-22 “索引/键”对话框 图4-23 创建UNIQUE约束
应当注意的是,在向表中的现有列添加UNIQUE约束时,默认情况下SQL Server 2000检查列中的现有数据,确保除NULL外的所有值均唯一。如果对有重复值的列添加UNIQUE约束,SQL Server在保存约束时将返回错误信息并不添加约束。错误信息中会提示重复键的位置,可能的错误信息如下:
'class' 表
- 不能创建索引'IX_class'。
ODBC 错误:[Microsoft][ODBC SQL Server Driver][SQL Server]CREATE UNIQUE INDEX 终止,因为发现了索引ID 2 的重复键。最重要的主键为'1'。
[Microsoft][ODBC SQL Server Driver][SQL Server]未能创建约束。请参阅前面的错误信息。
[Microsoft][ODBC SQL Server Driver][SQL Server]语句已终止。
CHECK约束通过限制输入到列中的值来强制域的完整性。这与FOREIGN KEY约束控制列中数值相似。区别在于它们如何判断哪些值有效:FOREIGN KEY约束从另一个表中获得有效数值列表,CHECK约束从逻辑表达式判断而非基于其他列的数据。实施了CHECK约束后,将拒绝所有不满足CHECK约束的值,即不接受所有使得约束表达式值为FALSE的值。
例如,要在学生选课成绩表sc中使用CHECK约束来限定score列只能为0到100分,可以在sc的设计表窗口中右击,在弹出的快捷菜单中选择“CHECK约束”菜单项,弹出如图4-24所示对话框。
图4-24 CHECK约束选项卡
其中,“约束名”标签后的文本框中自动给出新约束的名称,默认情况下为“CK_表名”,在本例中为“CK_sc”,用户可以在文本框指定自定义的名称。
单击“新建”按钮,在“约束表达式”标签下方的编辑框中可以输入CHECK约束表达式。
在约束表达式中,可以使用算术运算符、位运算符、比较运算符或字符串运算符,也还可以使用函数、常数、变量、列名等。在本例中要将score限制在0到100之间,可以在编辑框中输入“score>=0 AND score<=100”,表明score必须大于等于0,同时,必须小于等于100。若使用“BETWEEN”运算符,上述表达式可以表示成“score BETWEEN 0 AND 100”。关于运算符、函数等知识,将在第6章中详细介绍。
若表中已经包含了数据记录行,则可以单击选择“创建中检查现存数据”复选框,从而使得在创建CHECK约束的过程中检查已有的数据是否满足该约束。
输入完成后,如图4-25所示,单击“关闭”按钮即可退回至设计窗口。
图4-25 创建CHECK约束
若现有的数据不满足新建的约束,则系统会给出错误提示,可能的提示为:
'sc' 表
- 不能添加约束'CK_sc'。
ODBC 错误:[Microsoft][ODBC SQL Server Driver][SQL Server]ALTER TABLE 语句与COLUMN CHECK 约束'CK_sc' 冲突。该冲突发生于数据库'new',表'sc', column 'score'。
若满足了约束的条件,即可保存表的设计从而退出。但当插入新记录时,若不满足该约束,也会给出错误提示,可能的错误提示如图4-26所示。
图4-26 不满足CHECK约束
如果在插入行时没有指定列的值,或者希望使用当前时间值等,则可以使用默认值来指定列的初始值。默认值可以是取值为常量的任何对象。
在SQL Server 2000中,有3种使用默认值的方法。
在创建表,或者在修改表的结构时,在企业管理器中的表设计窗口,选择要设定默认值的列,然后在其下方的默认值栏中输入默认值。
例如,一个学校的男老师较多,因此可以将“性别”列的默认值设置为“男”,则可以打开teacher表的设计窗口,选择“性别”列,再在其下方的“默认值”栏右侧输入“'男'”,如图4-27所示。
图4-27 指定列的默认值
在创建表或者更改表时,字段的数据类型后加上“DEFAULT( )”关键字,再在其中的括号中指定默认值即可。如果要将teacher表中的年龄默认值设为40岁,则在建立年龄字段时,输入如下语句即可指定其默认值:
年龄smallint DEFAULT (40)
上述两种方法在删除表时,默认值就会被删除,但是在某个数据库中,如果经常使用某个默认值,可以考虑创建默认对象,它是单独存储的,即使表被删除,也不会受到影响。另外,在创建默认对象后,一般都需要将其绑定到某列或者用户自定义的数据类型上。在使用默认对象时,先要创建默认对象,再绑定使用默认对象。
(1)创建默认对象。
① 首先打开企业管理器,选择要创建默认对象的数据库,这里选择new数据库,单击其左侧的“+”,程序将会展开其中各个节点,右击“默认”节点,在弹出的快捷菜单中选择“新建默认”菜单项,如图4-28所示。
图4-28 选择新建默认
② 选择“新建默认”菜单项后,程序即弹出如图4-29所示窗口。在“名称”标签后的文本框中可以指定新建默认的名称,而在“值”标签后的文本框中可以指定默认的值。例如,可以指定默认对象的名称为“性别”,值为“'男'”,此处,作为字符串,其左右一定需要用单引号(')隔开。
图4-29 默认属性窗口
③ 单击“确定”按钮,即可保存对象,退回至企业管理器窗口。此时在企业管理器中已经可以看到新建的默认对象。
(2)绑定默认对象。
建立好默认对象后,要使用该对象,例如要将“teacher”表中“性别”字段与“性别”默认对象绑定,则可以按照以下操作步骤来实现。
① 首先,打开企业管理器,展开服务器组,并展开相应的服务器。
② 然后打开相应的数据库,并在其中找到默认对象,在本例中选择new数据库,并找到“性别”默认对象。
③ 双击该默认对象,或者右击该对象,在弹出的快捷菜单中选择“属性”菜单项,弹出如图4-30所示属性窗口,在其中还可以更改默认对象的值。
图4-30 查看已建默认属性
④ 单击“绑定列”按钮,弹出如图4-31所示窗口。在其中的下拉选择框中可以选择要绑定的列所在的数据表,在本例中选择[dbo].[teacher]数据表,选定后,即可看到该表中各列的与默认对象的绑定情况。其中左侧列表中为所有未绑定的列的名称及其数据类型,右侧列表中为已绑定的列的信息。
图4-31 将默认值绑定到列
⑤ 在图4-31左侧的“未绑定的列”列表中选择要绑定的列,这里选择“性别”,然后单击窗口中间的“添加”按钮,该列就会从左侧列表中删除而添加到右侧的“绑定列”列表中,如图4-32所示。
图4-32 添加绑定列
若还需要添加其他数据表中的列,可以按照如上的步骤,先选择数据表,再选择要绑定的列。确定添加完毕后,单击“确定”按钮,即可将“性别”默认对象绑定到teacher表中的“性别”列。
值得注意的是,如果已经使用前两种方法指定了列的默认值,则不能再使用默认对象绑定,否则在保存绑定时,系统会给出错误提示,提示“不能为创建时具有默认值或更改为具有默认值的列绑定默认值”,如图4-33所示。
图4-33 绑定列错误
如果要将默认对象绑定到UDT(用户自定义数据类型),则在如图4-30所示的步骤时,单击“绑定UDT”按钮,接下来步骤与绑定列相似,不再赘述。
(3)重命名默认对象。
建立默认对象后,并不能通过属性来更改默认对象的名称,如图4-30所示,其中“名称”标签后的文本框无法编辑。所以要更改默认对象的名称,可以直接在企业管理器中更改。
在企业管理器中,选择要重命名的默认对象,然后单击鼠标右键,在弹出的快捷菜单中选择“重命名”菜单项,或者直接按F2键,然后直接在激活的名称标签中进行编辑。
(4)删除默认对象。
在删除默认对象之前,首先要确认默认对象未绑定到任何对象上,否则将无法删除。
删除对象时,在企业管理器中选择要删除的默认对象,然后单击鼠标右键,在弹出的快捷菜单中选择“删除”菜单项,或者在选中对象后直接按Delete键,然后会弹出如图4-34所示对话框。对话框的列表中列出了所有即将要删除的默认对象,确认无误后,单击“全部除去”按钮。
图4-34 除去默认对象
如果默认对象被绑定到列或UDT上,系统会给出错误提示,如图4-35所示。本例中的出错原因为“性别”默认对象绑定到了一个或多个列上。
图4-35 除去默认对象错误
如果确实要删除该默认对象,可以先在默认对象属性中删除绑定,即在图4-32所示的步骤中,单击已绑定的对象,再单击“删除”按钮。解除所有绑定后,再按上述步骤操作,即可删除该对象。
规则可用于执行一些与CHECK约束相同的功能,它可以限制存储在表中或者用户自定义数据类型的值,也可以使用多种方式对数据值进行检验,可以使用函数返回验证信息,也可以使用BETWEEN、LIKE等关键字完成对输入数据的检查。
跟规则相比,CHECK约束是用来限制列值的首选的标准方法,CHECK约束比规则更简明,一个列只能应用一个规则,但是却可以应用多个CHECK约束。规则也有其独特的优点,它是以单独的对象创建,然后再绑定到列上,这一点与“默认对象”很相似,只有将其绑定到列或用户自定义数据类型上时才能起作用。
创建规则时,首先要打开需要建立规则的数据库,然后右击“规则”节点,在弹出的快捷菜单中选择“新建规则”菜单项,即弹出如图4-36所示对话框。在“名称”标签后的文本框中可以指定新建规则的名称,在“文本”标签后的编辑框中可以编辑要创建的规则表达式。
规则中的表达式与CHECK约束中的表达式语法并不相同,规则表达式中不能出现列名,只能包含一个变量,该变量可以出现多次,该变量必须以“@”开头,该变量将会引用更新记录或者插入记录时输入的值,另外,可以在表达式中使用算术运算符、比较运算符等多种运算符。
图4-36 创建规则对话框
例如,若要将“teacher”表中的“性别”的值限定为“男”或“女”,则可以在“文本”标签后的编辑框中输入“@c='男' OR @c='女'”,其中变量“@c”可以为其他任何名称,都将引用更新数据时所输入的值。
表达式输入完成后,单击“确定”按钮保存退出。
将规则绑定到列与默认对象的操作相似,不再赘述。
绑定完成后,若输入的新数据不满足条件时,比如当“性别”列中输入“男”或“女”之外的其他值时,系统将给出错误信息,可能的出错信息如图4-37所示。
图4-37 规则冲突
解除规则绑定和删除规则与默认对象的操作类似,要删除规则之前也必须保证规则的所有绑定已经解除。