数据库一致性、完整性

时间:2023-01-26 23:43:08

来源:

http://www.zybang.com/question/e23cf724ee5a0d00d2cba4f9ccb2d23b.html

https://zhidao.baidu.com/question/53409759.html 


数据完整性(data integrity)是
 指数据的精确性(accuracy) 和可靠性(reliability)。它是应防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。数据完整性分为四类:实体完整性(entity integrity)、域完整
 性(domain integrity)、参照完整性(referential integrity)、用户定义的完整性(user-definedintegrity)。


 保证数据的完整性:
 1. 用约束而非商务规则强制数据完整性

 如果 按照商务规则来处理需求,那么 应当检查商务层次/用户界面:如果商务规则以后发生变化,那么只需要进行更新即可。

 假如需求源于维护数据完整性的需要,那么在数据库层面上需要施加限制条件。

 如果 在数据层确实采用了约束, 要保证有办法把更新不能通过约束检查的原因采用用户理解的语言通知用户界面。除非 的字段命名很冗长,否则字段名本身还不够。 ? lamont adams

 只要有可能,请采用数据库系统实现数据的完整性。这不但包括通过标准化实现的完整性而且还包括数据的功能性。在写数据的时候还可以增加触发器来保证数据的正确性。不要依赖于商务层保证数据完整性;它不能保证表之间(外键)的完整性所以不能强加于其他完整性规则之上。

 ? peter ritchie

 2. 分布式数据系统

 对分布式系统而言,在 决定是否在各个站点复制所有数据还是把数据保存在一个地方之前应该估计一下未来5 年或者10 年的数据量。当 把数据传送到其他站点的时候,最好在数据库字段中设置一些标记。在目的站点收到 的数据之后更新 的标记。为了进行这种数据传输,请写下 自己的批处理或者调度程序以特定时间间隔运行而不要让用户在每天的工作后传输数据。本地拷贝 的维护数据,比如计算常数和利息率等,设置版本号保证数据在每个站点都完全一致。

 ? suhair techrepublic

 3. 强制指示完整性

 没有好办法能在有害数据进入数据库之后消除它,所以 应该在它进入数据库之前将其剔除。激活数据库系统的指示完整性特性。这样可以保持数据的清洁而能迫使开发人员投入更多的时间处理错误条件。

 ? kol

 4. 关系

 如果两个实体之间存在多对一关系,而且还有可能转化为多对多关系,那么 最好一开始就设置成多对多关系。从现有的多对一关系转变为多对多关系比一开始就是多对多关系要难得多。

 ? cs data architect

 5. 采用视图

 为了在 的数据库和 的应用程序代码之间提供另一层抽象, 可以为 的应用程序建立专门的视图而不必非要应用程序直接访问数据表。这样做还等于在处理数据库变更时给 提供了更多的*。

 ? gay howe

 6. 给数据保有和恢复制定计划

 考虑数据保有策略并包含在设计过程中,预先设计 的数据恢复过程。采用可以发布给用户/开发人员的数据字典实现方便的数据识别同时保证对数据源文档化。编写在线更新来“更新查询”供以后万一数据丢失可以重新处理更新。

 ? kol

 7. 用存储过程让系统做重活

 解决了许多麻烦来产生一个具有高度完整性的数据库解决方案之后, 所在的团队决定封装一些关联表的功能组,提供一整套常规的存储过程来访问各组以便加快速度和简化客户程序代码的开发。在此期间, 发现3gl 编码器设置了所有可能的错误条件,比如以下所示:

 select cnt = count (*)

 from []

 where [] = 

 if cnt = 0

 begin

 insert into []

 ( [< primary key column>] )

 values (  )

 end

 else

 begin

 

 end

 而一个非3gl 编码器是这样做的:

 insert into []

 ( [< primary key column>] )

 values

 (  )

 if @@error = 2627 -- literal error code for primary key constraint

 begin

 

 end

 第2 个程序简单多了,而且事实上,利用了 给数据库的功能。虽然 个人不喜欢使用嵌入文字(2627)。但是那样可以很方便地用一点预先处理来代替。数据库不只是一个存放数据的地方,它也是简化编码之地。

 ? a-smith

 8. 使用查找

 控制数据完整性的最佳方式就是限制用户的选择。只要有可能都应该提供给用户一个清晰的价值列表供其选择。这样将减少键入代码的错误和误解同时提供数据的一致性。某些公共数据特别适合查找:国家代码、状态代码等

 数据的完整性和一致性
概述
数据库设计中的一个重要步骤是确定实现数据完整性的方案。

数据完整性:存储在数据库中的所有数据值均正确的状态。

强制数据完整性:可确保数据库中数据的质量。例如,如果输入了学号值为001的学生,那么该数据库不应允许其他学生使用同一学号值。如果语文成绩列的值范围设定为从 0 到 100,则数据库不应接受101。如果表有一列名为班级,该列存储学生班级编号,则数据库应只允许接受学校中的有效的班级编号。

对表进行计划有两个重要步骤:标识列的有效值和确定如何强制列中的数据完整性。数据完整性有四种类型:
? 实体完整性(Entity Integrity)
实体完整性将行定义为特定表的唯一实体。实体完整性强制表的标识符列(ID)或主键的完整性(通过索引、UNIQUE 约束、PRIMARY KEY 约束或 IDENTITY 属性)。
? 域完整性(Domain Integrity)
域完整性是指给定列的输入有效性。强制域有效性的方法有:限制类型(通过数据类型)。、格式(通过 CHECK 约束和规则)或可能值的范围(通过 FOREIGN KEY 约束、CHECK 约束、DEFAULT 定义、NOT NULL 定义和规则)。
? 引用完整性(Reference Integrity)
在输入或删除记录时,引用完整性保持表之间已定义的关系。在SQL Server 2000 中,引用完整性基于外键与主键之间的关系(通过FOREIGN KEY 和 CHECK 约束)。引用完整性确保键值在所有表中一致。这样的一致性要求不能引用不存在的值,如果键值更改了,那么在整个数据库中,对该键值的所有引用要进行一致的更改。












强制引用完整性时,SQL Server 禁止用户进行下列操作:
? 当主表中没有关联的记录时,将记录添加到相关表中。例如,在学生成绩表中添加一个学生的学习成绩,而学生档案表中却没有该学生的注册信息。
? 更改主表中的值并导致相关表中的记录孤立。例如,在学生成绩表中有某个学生的学习成绩,而学生档案表中该学生的注册信息已被修改。
? 从主表中删除记录,但仍存在与该记录匹配的相关记录。例如,在学生成绩表中有某个学生的学习成绩,而学生档案表中该学生的注册信息已被删除。

举例,对于pubs数据库中的sales和titles表,引用完整性基于sales表中的外键 (title_id)与titles表中的主键 (title_id) 之间的关系。

? 用户定义完整性(User Defined Integrity)
用户定义完整性使您得以定义不属于其它任何完整性分类的特定业务规则。所有的完整性类型都支持用户定义完整性(CREATE TABLE 中的所有列级和表级约束、存储过程和触发器)。
数据的完整性图示

SQL Server中数据的完整性和一致性
SQL Server提供了六种约束来保证数据的完整性和一致性。
  (1) PRIMARY KEY 主键约束(行)
  (2) FOREIGN KEY 外键约束(表间)
  (3) UNIQUE 唯一性约束(行)
  (4) CHECK 检查约束(列)
  (5) DEFAULT 缺省值约束(列)
  (6) NULL 空值(列)

下面我们详细说明这六种约束:
(1) PRIMARY KEY 主键(PK)约束(行)
表中经常有一个列或列的组合,其值能唯一地标识表中的每一行,这样的一列或多列称为表的主键。通过主键可强制表的实体完整性。当创建或更改表时可通过定义PRIMARY KEY约束来创建主键。

实体完整性是这样一种状态:数据库中的所有行都具有一个非空的主键值,所有表都具有主键,且没有具有重复的主键值的表。这确保数据库中所代表的任何事物均不存在重复的条目。

主键是唯一标识表中的所有行的一个列或一组列。主键不允许空值。不能存在具有相同的主键值的两个行,因此主键值总是唯一标识单个行。表中可以有不止一个键唯一标识行,每个键都称作候选键。只有一个候选键可以选作表的主键,所有其它候选键称作备用键。尽管表不要求具有主键,但定义主键是很好的做法。 在规范化的表中,每行中的所有数据值都完全依赖于主键。例如,在以EmployeeID作为主键的规范化的employee表中,所有列都应包含与某个特定职员相关的数据。该表不具有DepartmentName列,因为部门的名称依赖于部门ID,而不是职员ID。
一个表只能有一个PRIMARY KEY约束,而且PRIMARY KEY约束中的列不能接受空值。由于PRIMARY KEY约束确保唯一数据,所以经常用来定义标识列。

标识列:表中已指派了标识属性的列。标识属性生成唯一数字。

当为表指定PRIMARY K EY约束时,SQL Server 2000 通过为主键列创建唯一索引强制数据的唯一性。当在查询中使用主键时,该索引还可用来对数据进行快速访问。

唯一索引:一种索引,不允许具有索引值相同的行,从而禁止重复的索引或键值。系统在创建该索引时检查是否有重复的键值,并在每次使用INSERT或UPDATE语句添加数据时进行检查。

如果 PRIMARY KEY 约束定义在不止一列上,则一列中的值可以重复,但PRIMARY KEY约束定义中的所有列的组合的值必须唯一。如下图所示,titleauthor表中的au_id和title_id列组成该表的组合PRIMARY KEY约束,以确保au_id和title_id的组合唯一。


当进行联接时,PRIMARY KEY约束将一个表与另一个表相联。例如,若要确定作者与书名的对应关系,可以使用authors表、titles表和titleauthor表的三向联接。因为titleauthor包含 au_id和title_id两列,对titles表的访问可由titleauthor和titles之间的关联进行。

一个 PRIMARY KEY 约束可以:作为表定义的一部分在创建表时创建。
添加到尚没有 PRIMARY KEY 约束的表中(一个表只能有一个 PRIMARY KEY 约束)。
如果已有 PRIMARY KEY约束,则可对其进行修改或删除。例如,可以使表的 PRIMARY KEY 约束引用其它列,更改列的顺序、索引名、聚集选项或PRIMARY KEY 约束的填充因子。定义了 PRIMARY KEY 约束的列的列宽不能更改。
说明 若要使用 Transact-SQL 或 SQL-DMO 修改 PRIMARY KEY,必须先删除现有的PRIMARY KEY 约束,然后再用新定义重新创建。
当向表中的现有列添加 PRIMARY KEY约束时,Microsoft&reg; SQL Server?2000 检查列中现有的数据以确保现有数据遵从主键的规则:
无空值
无重复值
如果 PRIMARY KEY 约束添加到具有空值或重复值的列上,SQL Server 不执行该操作并返回错误信息。不能添加违背上述规定的PRIMARY KEY 约束。
SQL Server 自动创建唯一的索引来强制 PRIMARY KEY约束所要求的唯一性。如果表中不存在聚集索引或未明确指定非聚集索引,则将创建唯一的聚集索引强制 PRIMARY KEY 约束。
重要 当 PRIMARY KEY 约束由另一表的 FOREIGN KEY 约束引用时,不能删除 PRIMARY KEY 约束;要删除它,必须先删除 FOREIGN KEY 约束。
在创建表时创建 PRIMARY KEY 约束
Transact-SQL参考(点击查看)
在现有表中创建或删除 PRIMARY KEY 约束
Transact-SQL参考(点击查看)
企业管理器:
(定义主键
定义主键来强制不允许空值的指定列中输入值的唯一性。如果在数据库中为表定义了主键,则可将该表与其它表相关,从而减少冗余数据。表只能有一个主键。
定义主键
在数据库关系图或表设计器中,单击要定义为主键的数据库列的行选择器。若要选择多个列,请按住 CTRL 键同时单击其它列的行选择器。
右击列的行选择器,然后选择"设置主键"命令。将自动创建一个名为"PK_"且后跟表名的主键索引;可在属性页的"索引/键"选项卡上找到该索引。
警告 如果要重新定义主键,则必须先删除任何与现有主键相关的关系才能创建新主键。将出现一条信息,警告您作为该过程的一部分,将自动删除现有关系。
行选择器上的主键符号 用于标识一个主键列。
如果主键包含不止一列,则在一列中允许有重复值,但主键中所有列值的每个组合必须唯一。
如果定义复合键,主键中的列顺序将与关系图中的表所显示的列顺序相匹配。不过,可以在创建主键后更改列的顺序。
删除主键约束
当要删除对列或列组合中的输入值的唯一性要求时,删除主键约束。 
删除主键约束
在数据库关系图或表设计器中,选择要删除主键约束的表的主键列。行选择器上的主键符号 用于标识一个主键列。
右击列的行选择器,然后选择"设置主键"命令。
–-或-–
在数据库关系图中选择要删除主键约束的表。
右击表并选择"索引/键"命令。
从"选定的索引"列表中选择主键索引。
选择"删除"按钮。
注意 选择"删除"按钮将导致一个无法撤消的操作,而且不保存对数据库关系图所做的所有其它更改。若要撤消该操作,请不保存更改即关闭当前的数据库关系图和所有其它打开的数据库关系图。
当保存表或关系图时,约束即从数据库中被删除。
)
修改 PRIMARY KEY 约束
(修改主键
当要更改列顺序、索引名称、聚集选项或填充因子时,修改主键。
修改主键
在数据库关系图中右击要修改主键的表,然后从快捷菜单中选择"属性"命令。
-或-
为要修改主键的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"属性"命令。
选择"索引/键"选项卡。
从"选定的索引"列表中选择主键索引。
完成下表中的操作:

当保存表或关系图时,主键即在数据库内被更新。)

(2) FOREIGN KEY 外键(FK)约束(表间)
外键约束与主键约束或唯一约束(UNIQUE约束)一起在指定表中强制引用完整性。例如,可以在publishers表的title_id列中放置一个外键约束,以保证这一列中的输入值与titles表 title_id列中的现有值匹配。

外键是列或列的组合,其值与同一个表或另一个表中的主键 (PK) 或唯一键相匹配。也称作参照键。

UNIQUE 约束:强制非主键上的实体完整性的约束。UNIQUE约束确保未输入重复值,并创建一个索引以增强性能。

在数据库关系图中,当创建从一个附加了主键约束或唯一约束的表到另一个表之间的关系时,外键约束将自动添加到指定的列上。


1、 查看外键特性
当要查看在关系中作为外键方的列时,查看关系的外键特性。如果外键列与主键相关,那么数据库图关系图中的主键列由行选择器中的主键符号标识。
查看关系的外键特性
I、在数据库关系图中,右击对应于外键的关系线,然后从快捷菜单中选择"属性"命令。
-或-
为包含要修改的外键的表打开表设计器,在表设计器中右击,然后从快捷式菜单中选择"属性"命令。
II、选择"关系"选项卡。
III、从在"选定的关系"列表中选定关系。
IV、"外键表"列显示了在关系中作为外键方的每一列的名称。

2、修改外键
当要更改与主键表中的列相关的列时,修改关系的外键方。
修改外键
I、在数据库关系图中右击与要修改的外键对应的关系,然后从快捷菜单中选择"属性"命令。
-或-
为包含要修改的外键的表打开表设计器,在表设计器中右击,然后从快捷式菜单中选择"属性"命令。
II、选择"关系"选项卡。
III、从"选定的关系"列表中选择关系。
IV、在"外键表"列中,展开第一行中的列表。
V、从列表中选择不同的表列。外键列必须与主键列的数据类型及大小相匹配,下面3种情况除外:
char 列或 sysname 列可以与 varchar 列相关。
binary 列可以与 varbinary 列相关。
用户定义数据类型可以与其基本类型相关。
只要一移出属性页的网格,对关系属性所做的任何更改即生效。当保存表或关系图时,约束即在数据库内被更新。

注意 在数据库关系图中修改关系时,相关的两个表均被标记为已修改。因此,每个表在任何其它包含该表的关系图中也被标记为已修改。

3、创建 CHECK 约束时检查现有数据
当创建关系时,如果需要对现有数据以及新数据应用外键约束,则选择该选项以检查现有数据。
创建 CHECK 约束时检查现有数据
I、在数据库关系图中选择附加了外键约束的表。
II、右击表并选择"属性"命令。
III、选择"关系"选项卡。
IV、从"选定的关系"列表中选择关系。
V、选择"创建中检查现存数据"复选框。
保存表或关系图时将应用外键约束。如果在保存过程中遇到任何违反约束的行为,则不能保存表。

4、对 INSERT 和 UPDATE 语句禁用外键约束
如果知道新数据将违反约束或约束仅应用于数据库中的现有数据,则选择该选项以在INSERT 和 UPDATE 事务期间禁用外键约束。
对 INSERT 和 UPDATE 语句禁用外键约束
I、在数据库关系图中,右击包含外键的表,然后从快捷菜单中选择"属性"命令。
-或-
为包含要修改的外键的表打开表设计器,在表设计器中右击,然后从快捷式菜单中选择"属性"命令。
II、选择"关系"选项卡。
III、从"选定的关系"列表中选择关系。
IV、清除"对 INSERT 和 UPDATE 强制关系"复选框。
添加或修改数据后,若要确保约束能应用到后续的数据修改中,应该选择该选项。
注意 如果打算使用触发器执行数据库操作,则必须禁用外键约束才能使触发器运行。

5、对复制禁用外键约束
SQL Server 支持复制。如果约束针对源数据库,并且可能会不必要地阻止新数据输入到目的数据库中,则选择该选项以在复制期间禁用外键约束。
对复制禁用外键约束
I、在数据库关系图中,右击包含外键的表,然后从快捷菜单中选择"属性"命令。
-或-
为包含要修改的外键的表打开表设计器,在表设计器中右击,然后从快捷式菜单中选择"属性"命令。
II、选择"关系"选项卡。
III、从"选定的关系"列表中选择关系。
IV、清除"对复制启用关系"复选框。

6、删除外键约束
当要删除强制引用完整性要求时,删除外键。
删除外键约束
在数据库关系图中,删除代表要删除的外键约束的关系线。
注意 从数据库关系图中删除关系时,相关表在所有包含它的关系图中将被标记为已修改。

(3) UNIQUE 唯一性约束(行)
对于一个表中非主键列的指定列,唯一约束确保不会输入重复的值。例如,在 employee 表中 emp_id 列是主键,可以定义一个唯一约束来要求表中社会安全号码 (ssn) 列的项是唯一的。

UNIQUE约束:强制非主键上的实体完整性的约束。UNIQUE约束确保未输入重复值,并创建一个索引以增强性能。

在数据库关系图中,可以使用"索引/键"属性页创建、修改或删除唯一约束。


1、创建唯一约束
创建唯一约束来确保不参与主键的特定列的值不重复。尽管唯一约束和主键都强制唯一性,但在下列情况下,应该为表附加唯一约束以取代主键约束:

如果要对列或列的组合强制唯一性。可以为表附加多个唯一约束,而只能为表附加一个主键约束。

如果要对允许空值的列强制唯一性。可以为允许空值的列附加唯一约束,而只能将主键约束附加到不允许空值的列。当将唯一约束附加到允许空值的列时,确保在约束列中最多有一行含有空值。

创建唯一约束
I、在数据库关系图中右击将包含约束的表,然后从快捷菜单中选择"属性"命令。
-或-
为将包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"属性"命令。
II、选择"索引/键"选项卡。
III、选择"新建"命令。系统分配的名称出现在"索引名"框中。
IV、在"列名"下展开列的列表,选择要将约束附加到的列。若要将约束附加到多个列,在后续行中选择其它的列。
当保存表或关系图时,唯一约束即创建在数据库中。
如果使用的是 SQL Server,可以控制键值的排序次序以及当存在重复键时所采取的操作。为此,应创建唯一索引取代唯一约束。

2、修改唯一约束
当要更改约束附加到的列、更改约束名称或设置附加属性时,修改唯一约束。
修改唯一约束
I、在数据库关系图中右击包含约束的表,然后从快捷菜单中选择"属性"命令。
-或-
为包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"属性"命令。
II、选择"索引/键"选项卡。
III、从"选定的索引"列表中选择要更改的约束。
IV、完成下表中的操作:

当保存表或关系图时,约束即在数据库内被更新。

3、删除唯一约束
当要删除对包含在约束表达式中的列或列组合中输入值的唯一性要求时,删除唯一约束。
删除唯一约束
I、在数据库关系图中,右击包含约束列的表,然后从快捷菜单中选择"索引/键"命令。
-或-
为包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"索引/键"命令。
II、从"选定的索引"列表中选择唯一约束。
III、选择"删除"按钮。
注意 选择"删除"按钮将导致一个无法撤消的操作,而且不保存对数据库关系图所做的所有其它更改。若要撤消该操作,不保存更改即关闭当前的数据库关系图或表设计器窗口以及所有其它打开的数据库关系图和表设计器窗口。
当保存表或关系图时,约束即从数据库中被删除。

演示
所谓唯一性约束(unique constraint)不过是数据表内替代键的另一个名称而已。替代键(alternate key)可以是数据表内不作为主键的其他任何列,只要该键对该数据表唯一即可。换句话说,在唯一列内不允许出现数据重复的现象。比方说,你可以用车辆识别代号(VIN)作为汽车(Automobile)数据表的替代键,在汽车数据表里,主键是汽车识别号(Automobile Identification),这是一种由系统自动成的ID。你可以在汽车表内对VIN施加唯一性约束,同时再创建一个需要VIN的表。在这个新表内可以声明外键指向汽车表。这样,只要汽车表内有VIN输入数据库就会检验VIN输入结果。这就是保证数据库内数据完整性的另一种有效的措施。

以下是演示唯一性约束作为外键引用点的示例代码:



(4) CHECK 检查约束(列)
CHECK 约束指定可由表中一列或多列接受的数据值或格式。例如,可以要求authors 表的 zip 列只允许输入五位数的数字项。可以为一个表定义许多CHECK 约束。可以使用"表"属性页创建、修改或删除每个CHECK 约束。

CHECK 约束定义列中可接受的数据值。可以将 CHECK 约束应用于多个列,也可以将多个 CHECK 约束应用于单个列。当除去某个表时,也将除去 CHECK 约束。



1、将新的 CHECK 约束附加到表或列
将 CHECK 约束附加到表以指定一列或多列中可接受的数据值。
附加新的 CHECK 约束
在数据库关系图中,右击包含约束的表,然后从快捷菜单中选择"约束"命令。
-或-
为将包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"约束"命令。
选择"新建"命令。"选定的约束"框显示由系统分配的新约束名。系统分配的名称以"CK_"开始,后跟表名。
在"约束表达式"框中,为 CHECK 约束键入 SQL 表达式。例如,若要将 authors 表中state 列的输入项限制为 New York,请键入:
state = 'NY'
或者,若要要求 zip 列中的输入项为 5 位数字,请键入:
zip LIKE '[0-9][0-9][0-9][0-9][0-9]'
若要给约束提供一个不同的名称,请在"约束名"框中键入名称。
用复选框控制何时强制约束:
若要在创建约束前对现有数据测试约束,请选中"创建中检查现存数据"复选框。
若要在该表中发生复制操作时强制约束,请选中"对复制强制约束"复选框。
若要在该表中插入或更新行时强制约束,请选中"对 IN SERT 和 UPDATE 强制约束"复选框。

2、定义 CHECK 约束表达式
当将 CHECK 约束附加到表或列时,必须包括 SQL 表达式。
可以创建简单的约束表达式在简单条件下检查数据;或使用布尔运算符创建复杂的约束表达式以在多种条件下检查数据。例如,假设 authors 表中有一个 zip 列,该列要求 5 位数字的字符串。下面的示例约束表达式确保只允许 5 位数字:
zip LIKE '[0-9][0-9][0-9][0-9][0-9]'
或者假设 sales 表中有一个名为 qty 的列,该列要求大于 0 的值。下面的示例约束确保只允许正值:
qty > 0
或者假设 orders 表限制所有信用卡订单可接受的信用卡类型。下面的示例约束确保如果用信用卡发出订单,则只接受 Visa、MasterCard 或 Ameri can Express:
NOT (payment_method = 'credit card') OR
(card_type IN ('VISA', 'MASTERCARD', 'AMERICA N EXPRESS'))
定义约束表达式
创建新的 CHECK 约束。
在属性页的"CHECK 约束"选项卡中,使用下列语法在"约束表达式"框中键入表达式:
{constant | column_name | functi on | (subquery)}
  [{operator | AND | OR | NOT}
  {constant | column_name | function | (subquery)} ...]
  SQL 语法由下列参数组成:


3、修改 CHECK 约束
当要更改约束表达式,或更改对特定条件启用或禁用约束的选项时,修改 CHECK 约束。
修改 CHECK 约束
I、在数据库关系图中右击包含约束的表,然后从快捷菜单中选择"属性"命令。
-或-
为包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"属性"命令。
II、选择"CHECK 约束"选项卡。
III、从"选定的约束"列表中,选择要更改的约束。
IV、完成下表中的操作:

当保存表或关系图时,约束即在数据库内被更新。

4、创建 CHECK 约束时检查现有数据
当创建 CHECK 约束时,可以设置选项将约束只应用于新数据或同时也应用于现有数据。当知道现有数据已满足新 CHECK 约束时,或者当业务规则要求仅从这点开始强制约束时,这种使约束仅应用于新数据的选项很有用。
例如,过去可能要求邮政编码必须是五位数字,但现在却需要新数据允许有九位邮政编码。包含五位邮政编码的旧数据将与包含九位邮政编码的新数据共存。
I、创建 CHECK 约束时检查现有数据
II、选择"CHECK 约束"选项卡。
III、从"选定的约束"列表中选择约束。
IV、选择"创建中检查现存数据"复选框。默认情况下选择该选项。
当保存表或数据库关系图时,将应用CHECK 约束。如果在保存过程中遇到任何违反约束的行为,则不能保存表。

5、对 INSERT 和 UPDATE 语句禁用 CHECK 约束
当在表中添加、更新或删除数据时,可以禁用 CHECK约束。禁用约束使您能够执行下列事务:

如果表中的现有行过去必须遵从的特定业务规则已不再适用,则可以向该表添加新的数据行(使用 INSERT 语句)。例如,过去可能要求邮政编码必须是五位数字,但现在却需要新数据允许有九位邮政编码。包含五位邮政编码的旧数据将与包含九位邮政编码的新数据共存。

如果表中的现有行过去必须遵从的特定业务规则已不再适用,则可以修改现有行(使用UPDATE 语句)。例如,可能需要将所有现有的五位邮政编码更新为九位邮政编码。
如果知道新数据将违反约束,或者约束仅适用于数据库中的已有数据,则选择该选项以在INSERT 和 UPDATE 事务处理期间禁用 CHECK 约束。

对 INSERT 和 UPDATE 语句禁用 CHECK 约束
I、在数据库关系图中右击包含约束的表,然后从快捷菜单中选择"属性"命令。
-或-
为包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"属性"命令。
II、选择"CHECK 约束"选项卡。
III、从"选定的约束"列表中选择约束。
IV、清除"对 INSERT 和 UPDATE 强制约束"复选框。
可以在添加或修改数据后选择该选项,以确保约束能应用到后续的数据修改中。

6、对复制禁用 CHECK 约束
当在另一个数据库中复制表时,可以禁用 CHECK 约束。复制表时,表定义和数据从源数据库复制到目的数据库。这两个数据库通常(但不一定)位于不同的服务器上。如果 CHECK约束仅针对源数据库,则可能会不必要地阻止新数据输入到目的数据库。当在远程站点上复制数据库时,不应重新应用 CHECK 约束,因为:
数据在被输入原始数据库时将进行完整性检查。

如果数据违反 CHECK 约束,复制将失败。
对复制禁用 CHECK 约束
I、在数据库关系图中右击包含约束的表,然后从快捷菜单中选择"属性"命令。
-或-
为包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"属性"命令。
II、选择"CHECK 约束"选项卡。
III、从"选定的约束"列表中选择约束。
IV、清除"对复制强制约束"复选框。

7、 删除 CHECK 约束
删除 CHECK 约束
当要删除对约束表达式包含的列所接受数据值的限制时,删除 CHECK 约束。
删除 CHECK 约束
I、在数据库关系图中右击包含约束的表,然后从快捷菜单中选择"属性"命令。
-或-
为包含约束的表打开表设计器,在表设计器中右击,然后从快捷菜单中选择"属性"命令。
II、选择"CHECK 约束"选项卡。
III、从"选定的约束"列表中选择约束。
IV、选择"删除"按钮。
注意 选择"删除"按钮将导致一个无法撤消的操作,而且不保存对数据库关系图所做的所有其它更改。若要撤消该操作,请不保存更改即关闭当前的数据库关系图和所有其它打开的数据库关系图。
当保存表或关系图时,约束即从数据库中被删除。

(5) DEFAULT 缺省值约束(列)
默认约束使您能够定义一个值,每当用户没有在某一列中输入值时,则将所定义的值提供给这一列。例如,在一个表的payterms 列中,可以让数据库服务器在用户没有输入时填上"???"或"fill in later"。

默认值是当用户未指定时由系统自动指派的数据值、选项设置、排序规则或名称。当用户未指定某些事件发生后要采取的操作时所自动采取的操作。

在数据库关系图中,可以将默认约束定义为表的一个列属性。通过在标准视图下的表内指定默认值,为列定义这种类型的约束。一定要指定带有正确分隔符的约束。例如,字符串必须用单引号括起来。

(6) NULL 空值(列)


SQL Server的空值处理策略
数据完整性是任何数据库系统要保证的重点。不管系统计划得有多好,空数据值的问题总是存在。本文探讨了在SQL Server中处理这些值时涉及的3个问题:计数、使用空表值以及外键处理。

用COUNT(*)处理空值
大多数集合函数都能在计算时消除空值;COUNT函数则属于例外。对包含空值的一个列使用COUNT函数,空值会从计算中消除。但假如COUNT函数使用一个星号,它就计算所有行,而不管是否存在空值。
事实上,对集合函数来说,如果空值可能导致错误结果,ISNULL函数就非常有用。记住在使用一个星号时,COUNT函数会对所有行进行计算。下例演示了空值在AVG和COUNT集合函数中的影响:

SET NOCOUNT ON
GO
CREATE TABLE xCount
(pkey1 INT IDENTITY NOT NULL
CONSTRAINT pk_xCount PRIMARY KEY, Col1 int NULL)
GO
INSERT xCount (Col1) VALUES (10)
GO
INSERT xCount (Col1) VALUES (15)
GO
INSERT xCount (Col1) VALUES (20)
GO
INSERT xCount (Col1) VALUES (NULL)
GO
SELECT AVG(Col1) AvgWithoutIsNullFunctionOnCol1
AVG(ISNULL(Col1,0)) AvgWithIsNullFunctionOnCol1,
COUNT(Col1) NoIs NullFunctionOnCol1 ,
COUNT(ISNULL(Col1,0)) UsingIsNullFunctionOnCol1,
Count(*) UsingAsterisk
FROM xCount
GO
DROP TABLE xCount 
GO

OUTPUT:


规则
规则是一个向后兼容的功能,用于执行一些与 CHECK约束相同的功能。CHECK 约束是用来限制列值的首选标准方法。CHECK 约束比规则更简明,一个列只能应用一个规则,但是却可以应用多个 CHECK 约束。CHECK 约束作为 CREATE TABLE语句的一部分进行指定,而规则以单独的对象创建,然后绑定到列上。

下例创建一个规则,执行与前面主题中的 CHECK 约束示例相同的功能。
Microsoft&reg; SQL Serve r? 2000 首选的方法是 CHECK 约束。

CREATE RULE id_chk AS @id BETWEEN 0 and 10000
GO
CREATE TABLE cust_sample
(
cust_id int
PRIMARY KEY,
cust_name char(50), 
cust_address char(50), 
cust_credit_limit money,
)
GO
sp_bindrule id_chk, 'cust_sample.cust_id'
GO



事务是指对系统进行的一组操作,为了保证系统的完整性,事务需要具有ACID特性,具体如下:
1. 原子性(Atomic)
     一个事务包含多个操作,这些操作要么全部执行,要么全都不执行。实现事务的原子性,要支持回滚操作,在某个操作失败后,回滚到事务执行之前的状态。
     回滚实际上是一个比较高层抽象的概念,大多数DB在实现事务时,是在事务操作的数据快照上进行的(比如,MVCC),并不修改实际的数据,如果有错并不会提交,所以很自然的支持回滚。
     而在其他支持简单事务的系统中,不会在快照上更新,而直接操作实际数据。可以先预演一边所有要执行的操作,如果失败则这些操作不会被执行,通过这种方式很简单的实现了原子性。


2. 一致性(Consistency)
     一致性是指事务使得系统从一个一致的状态转换到另一个一致状态。事务的一致性决定了一个系统设计和实现的复杂度。事务可以不同程度的一致性:
     强一致性:读操作可以立即读到提交的更新操作。
     弱一致性:提交的更新操作,不一定立即会被读操作读到,此种情况会存在一个不一致窗口,指的是读操作可以读到最新值的一段时间。
     最终一致性:是弱一致性的特例。事务更新一份数据,最终一致性保证在没有其他事务更新同样的值的话,最终所有的事务都会读到之前事务更新的最新值。如果没有错误发生,不一致窗口的大小依赖于:通信延迟,系统负载等。
     其他一致性变体还有:
     单调一致性:如果一个进程已经读到一个值,那么后续不会读到更早的值。
     会话一致性:保证客户端和服务器交互的会话过程中,读操作可以读到更新操作后的最新值。


3. 隔离性(Isolation)
     并发事务之间互相影响的程度,比如一个事务会不会读取到另一个未提交的事务修改的数据。在事务并发操作时,可能出现的问题有:
     脏读:事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,如果事务A提交失败,事务B读到的就是脏数据。
     不可重复读:在同一个事务中,对于同一份数据读取到的结果不一致。比如,事务B在事务A提交前读到的结果,和提交后读到的结果可能不同。不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这回导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。
     幻读:在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。
     事务的隔离级别从低到高有:
     Read Uncommitted:最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。
     Read Committed:只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。
     Repeated Read:在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。
     Serialization:事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。
     通常,在工程实践中,为了性能的考虑会对隔离性进行折中。


4. 持久性(Durability)
     事务提交后,对系统的影响是永久的。


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


数据一致性通常指关联数据之间的逻辑关系是否正确和完整.而数据存储的一致性模型则可以认为是存储系统和数据使用者之间的一种约定.如果使用者遵循这种约定,则可以得到系统所承诺的访问结果常用的一致性模型有:
a、严格一致性(linearizability, strict/atomic Consistency):读出的数据始终为最近写入的数据.这种一致性只有全局时钟存在时才有可能,在分布式网络环境不可能实现.
b、顺序一致性(sequential consistency):所有使用者以同样的顺序看到对同一数据的操作,但是该顺序不一定是实时的.
c、因果一致性(causal consistency):只有存在因果关系的写操作才要求所有使用者以相同的次序看到,对于无因果关系的写入则并行进行,无次序保证.因果一致性可以看做对顺序一致性性能的一种优化,但在实现时必须建立与维护因果依赖图,是相当困难的.
d、管道一致性(PRAM/FIFO consistency):在因果一致性模型上的进一步弱化,要求由某一个使用者完成的写操作可以被其他所有的使用者按照顺序的感知到,而从不同使用者中来的写操作则无需保证顺序,就像一个一个的管道一样. 相对来说比较容易实现.
e、弱一致性(weak consistency):只要求对共享数据结构的访问保证顺序一致性.对于同步变量的操作具有顺序一致性,是全局可见的,且只有当没有写操作等待处理时才可进行,以保证对于临界区域的访问顺序进行.在同步时点,所有使用者可以看到相同的数据.
f、 释放一致性(release consistency):弱一致性无法区分使用者是要进入临界区还是要出临界区, 释放一致性使用两个不同的操作语句进行了区分.需要写入时使用者acquire该对象,写完后release,acquire-release之间形成了一个临界区,提供 释放一致性也就意味着当release操作发生后,所有使用者应该可以看到该操作.
g、最终一致性(eventual consistency):当没有新更新的情况下,更新最终会通过网络传播到所有副本点,所有副本点最终会一致,也就是说使用者在最终某个时间点前的中间过程中无法保证看到的是新写入的数据.可以采用最终一致性模型有一个关键要求:读出陈旧数据是可以接受的.
h、delta consistency:系统会在delta时间内达到一致.这段时间内会存在一个不一致的窗口,该窗口可能是因为log shipping的过程导致.这是书上的原话.我也搞不很清楚.数据库完整性(Database Integrity)是指数据库中数据的正确性和相容性.数据库完整性由各种各样的完整性约束来保证,因此可以说数据库完整性设计就是数据库完整性约束的设计.包括实体完整性.域完整性.参照完整性.用户定义完整性.可以主键.check约束.外键来一一实现.这个使用较多.


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

数据完整性(Data Integrity)是
指数据的精确性(Accuracy) 和可靠性(Reliability)。它是应防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。数据完整性分为四类:实体完整性(Entity Integrity)、域完整
性(Domain Integrity)、参照完整性(Referential Integrity)、用户定义的完整性(User-definedIntegrity)。

保证数据的完整性:
1. 用约束而非商务规则强制数据完整性

如果你按照商务规则来处理需求,那么你应当检查商务层次/用户界面:如果商务规则以后发生变化,那么只需要进行更新即可。

假如需求源于维护数据完整性的需要,那么在数据库层面上需要施加限制条件。

如果你在数据层确实采用了约束,你要保证有办法把更新不能通过约束检查的原因采用用户理解的语言通知用户界面。除非你的字段命名很冗长,否则字段名本身还不够。 — Lamont Adams

只要有可能,请采用数据库系统实现数据的完整性。这不但包括通过标准化实现的完整性而且还包括数据的功能性。在写数据的时候还可以增加触发器来保证数据的正确性。不要依赖于商务层保证数据完整性;它不能保证表之间(外键)的完整性所以不能强加于其他完整性规则之上。

— Peter Ritchie

2. 分布式数据系统

对分布式系统而言,在你决定是否在各个站点复制所有数据还是把数据保存在一个地方之前应该估计一下未来5 年或者10 年的数据量。当你把数据传送到其他站点的时候,最好在数据库字段中设置一些标记。在目的站点收到你的数据之后更新你的标记。为了进行这种数据传输,请写下你自己的批处理或者调度程序以特定时间间隔运行而不要让用户在每天的工作后传输数据。本地拷贝你的维护数据,比如计算常数和利息率等,设置版本号保证数据在每个站点都完全一致。

— Suhair TechRepublic

3. 强制指示完整性

没有好办法能在有害数据进入数据库之后消除它,所以你应该在它进入数据库之前将其剔除。激活数据库系统的指示完整性特性。这样可以保持数据的清洁而能迫使开发人员投入更多的时间处理错误条件。

— kol

4. 关系

如果两个实体之间存在多对一关系,而且还有可能转化为多对多关系,那么你最好一开始就设置成多对多关系。从现有的多对一关系转变为多对多关系比一开始就是多对多关系要难得多。

— CS Data Architect

5. 采用视图

为了在你的数据库和你的应用程序代码之间提供另一层抽象,你可以为你的应用程序建立专门的视图而不必非要应用程序直接访问数据表。这样做还等于在处理数据库变更时给你提供了更多的*。

— Gay Howe

6. 给数据保有和恢复制定计划

考虑数据保有策略并包含在设计过程中,预先设计你的数据恢复过程。采用可以发布给用户/开发人员的数据字典实现方便的数据识别同时保证对数据源文档化。编写在线更新来“更新查询”供以后万一数据丢失可以重新处理更新。

— kol

7. 用存储过程让系统做重活

解决了许多麻烦来产生一个具有高度完整性的数据库解决方案之后,我所在的团队决定封装一些关联表的功能组,提供一整套常规的存储过程来访问各组以便加快速度和简化客户程序代码的开发。在此期间,我们发现3GL 编码器设置了所有可能的错误条件,比如以下所示:

SELECT Cnt = COUNT (*)

FROM [<Table>]

WHERE [<primary key column>] = <new value>

IF Cnt = 0

BEGIN

INSERT INTO [<Table>]

( [< primary key column>] )

VALUES ( <New value> )

END

ELSE

BEGIN

<indicate duplication error>

END

而一个非3GL 编码器是这样做的:

INSERT INTO [<Table>]

( [< primary key column>] )

VALUES

( <New value> )

IF @@ERROR = 2627 -- Literal error code for Primary Key Constraint

BEGIN

<indicate duplication error>

END

第2 个程序简单多了,而且事实上,利用了我们给数据库的功能。虽然我个人不喜欢使用嵌入文字(2627)。但是那样可以很方便地用一点预先处理来代替。数据库不只是一个存放数据的地方,它也是简化编码之地。

— a-smith

8. 使用查找

控制数据完整性的最佳方式就是限制用户的选择。只要有可能都应该提供给用户一个清晰的价值列表供其选择。这样将减少键入代码的错误和误解同时提供数据的一致性。某些公共数据特别适合查找:国家代码、状态代码等