加强数据完整性确保数据库中数据的质量。规划表时重要的两个步骤是鉴定列中值的有效性和如何加强列中数据的完整性。数据完整性可以分为四类,它们是以不同的方式进行加强的。 完整性类型 如何强制 Entity integrity PRIMARY KEY constraint Domain integrity Domain DEFAULT definition Referential integrity Domain DEFAULT definition User-defined integrity All column- and table-level constraints
in CREATE TABLE 实体完整性(Entity Integrity) 实体完整性把特定表中的一行作为一个唯一的实体加以定义。实体完整性通过索引、UNIQUE约束、PRIMARY
KEY约束或者IDENTITY特性加强表中标识列或者主关键字的完整性, 为约束命名 你总是可以显式的命名你的约束。如果你不这样做,Oracle和Microsoft SQL
Server将使用不同的命名惯例来隐式的为约束命名。在命名上的不同会为你的移植带来不必要的麻烦。在删除约束或者使约束失效时将会出现问题,因为约束必须通过名字来删除。显式命名约束的语法在Oracle和SQL
Server中是一样的。 CONSTRAINT
constraint_name 主键和唯一列 SQL-92标准要求主关键字中的所有值都是唯一的并且该列不允许空值。Oracle和Microsoft SQL
Server都是通过自动创建唯一的索引这种方式来强制实现唯一性的,无论是否定义了PRIMARY KEY或者UNIQUE约束。 虽然可以创建一个未分簇的索引,但是SQL
Server缺省的为主关键字创建一个分簇的索引。Oracle在主关键字上的索引可以通过删除约束或者使约束失效的方法来清除,而SQL
Server的索引只能通过删除约束来实现。 无论在哪种RDBMS中,其他关键字都可以定义一个UNIQUE约束。可以在任何表中定义多个UNIQUE约束。UNIQUE约束列可以为空。在SQL
Server中,除非另外说明,否则将缺省的创建一个未分簇的索引 在移植你的应用程序时,重要的是注意到SQL
Server只允许完全唯一的关键字(单个或者多个列索引)中有一行是NULL值的,而Oracle则允许完全唯一的关键字中任意行是NULL值。 Oracle Microsoft
SQL CREATE TABLE DEPT_ADMIN.DEPT CREATE TABLE
USER_DB.DEPT_ADMIN.DEPT 增加和清除约束 使约束失效可以改善数据库性能,并且使数据复制过程更加流畅。例如,当你在一个远程站点上重建或者复制表中的数据时,你不用重复约束检查,因为数据的完整性是在它原来输入数据库时就检查过的。你可以编制Oracle应用程序来使能或者失效约束(除了PRIMARY
KEY和UNIQUE)。你可以在Microsoft SQL Server的ALTER TABLE语句中使用CHECK和WITH
NOCHECK来达到同样的目的。 下面的插图显示了该过程的比较。 在SQL Server中,你在NOCHECK子句上使用ALL关键字来推迟所有的表的约束。 如果你的Oracle应用程序使用CASCADE选项来失效或者删除PRIMARY
KEY或者UNIQUE约束,你也许需要重写某些代码,因为CASCADE选项同时失效或者删除父类和子类的完整性约束。 这是关于语法的示例: DROP CONSTRAINT DEPT_DEPT_PK
CASCADE SQL Server应用程序必须修改成首先删除子类的约束,然后删除父类的约束。例如,为了删除DEPT表上的PRIMARY
KEY约束,STUDENT.MAJOR和CLASS.DEPT相关列的外部关键字必须被删除。这是语法的示例: ALTER TABLE STUDENT DROP CONSTRAINT
STUDENT_MAJOR_FK ALTER TABLE CLASS DROP CONSTRAINT
CLASS_DEPT_FK ALTER TABLE DEPT DROP CONSTRAINT
DEPT_DEPT_PK ALTER TABLE增加和删除约束的语法在Oracle和SQL Server中的语法是一样的。 生成连续的数字值 如果你的Oracle应用程序使用SEQUENCEs,该选项可以很容易的改变以利用Microsoft SQL
Server的IDENTITY特性。 类别 Microsoft SQL Server
语法 CREATE TABLE new_employees 每个表拥有的标识列 一个 允许空值 否 使用缺省约束、值 不能使用. 强制唯一 是 在INSERT, SELECT INTO 或者bulk copy 语句完成以后,查询最大的当前标识数 @@IDENTITY (function) 返回创建标识列时指定的种子值 IDENT_SEED('table_name') 返回创建标识列时指定的增加值 IDENT_INCR('table_name') SELECT语法 当在SELECT, INSERT, UPDATE,
和DELETE语句中引用带有IDENTITY属性的列时,可以在列名上使用IDENTOTY关键字 虽然IDENTITY特性使一个表中的行记数自动化,但是不同的表,如果每一个都有自己的标识列,可以产生同样的值。这是因为IDENTITY特性只能在使用它的表上被担保为唯一的。如果一个应用程序必须生成一个在整个数据库,或者全世界每一台联网计算机上的每一个数据库中唯一的标识列,可以使用ROWGUIDCOL特性,uniqueidentifier数据类型,以及NEWID函数。SQL
Server使用全局独立的标识列来并入复制,确保该行在所有该表的拷贝中是唯一的标识。 如果需要了解关于创建和修改标识列的更多信息,请参看SQL Server联机手册。 域完整性 域完整性约束对给定列的有效入口。域完整性是通过限制类型(通过数据类型),格式(通过CHECK约束),或者可能值的范围(通过REFERENCE和CHECK约束)来实现的。 DEFAULT和CHECK约束 Oracle把缺省(default)当作一个列属性来对待,而Microsoft SQL Server把缺省当作一个约束来对待。SQL
Server的DEFAULT约束可以包含整型值,内建的不带参数的函数(niladic函数),或者NULL。 要很方便的移植Oracle的DEFAULT列属性,你应该在SQL Server中定义列级别的不使用约束名字的DEFAULT约束。SQL
Server为每一个DEFAULT约束生成一个唯一的名字。 用来定义CHECK约束的语法在Oracle和SQL
Server中是一样的。搜索条件应该用布尔表达式来表示而且不能包含子查询。列级别的约束只能用在被约束列上,表级别的约束只能用在被约束的表中的列上。可以为一个表定义多个CHECK约束。SQL
Server语法允许在一个CREATE TABLE语句中只创建一个列级别的CHECK约束,并且该约束可以有多个条件。 测试你修改过的CREATE TABLE语句的最好方式是使用SQL Server中的SQL Server Query
Analyzer,并且只分析语法。输出结果将会指出任何错误。如果需要了解关于约束语法的更多信息,请参看SQL Server联机手册。 Oracle Microsoft SQL
CREATE TABLE STUDENT_ADMIN.STUDENT
( CREATE TABLE
USER_DB.STUDENT 关于用户定义规则和缺省(default)要注意:关于Microsoft SQL
Server规则和缺省的语法是考虑了向后兼容的,但是建议把CHECK约束和DEFAULT约束用在新的开发中。如果需要了解更多的信息,请参看SQL
Server联机手册。 Nullability Microsoft SQL Server和Oracle创建列约束来强制nullability。在Oracle的CREATE
TABLE和ALTER TABLE语句中,列缺省是NULL,而不是NOT NULL。在Microsoft SQL
Server,数据库和会话的设置可以越过在列定义中使用的数据类型的nullability。 你的所有的SQL脚本(无论是Oracle还是SQL Server),都必须显明的给出每一列的NULL和NOT
NULL定义。要了解这个策略是如何实现的,请参看Oracle.sql和Sstable.sql这两个示例的表创建脚本。如果没有显明的定义,则列的nullability遵循如下的规则。 Null settings Description
列是用一个用户定义数据类型定义的 SQL Server
使用在创建数据类型时指定的空值性。使用sp_help系统存储过程来获取数据类型的缺省的空值性 列是用一个系统提供的数据类型定义的 如果系统提供的数据类型只有一个选项,则优先使用该选项。当前, bit数据类型只能被定义为NOT
NULL。 NULL/NOT NULL 当没有显明的定义时(ANSI_NULL_DFLT选项一个都没有设定),会话将被修改,并且数据库被设定为缺省(ANSI
null default是false),然后SQL Server指定它为NOT
NULL。 引用完整性 下表提供了一个用来定义referential完整性约束的语法比较。 约束 Oracle Microsoft
SQL Server PRIMARY KEY [CONSTRAINT
constraint_name] [CONSTRAINT
constraint_name] UNIQUE [CONSTRAINT
constraint_name] [CONSTRAINT
constraint_name] FOREIGN KEY [CONSTRAINT
constraint_name] [CONSTRAINT
constraint_name] DEFAULT Column property, not a
constraint [CONSTRAINT
constraint_name] CHECK [CONSTRAINT
constraint_name] [CONSTRAINT
constraint_name] NOT FOR REPLICATION子句用来在复制过程中挂起列级别,FOREIGN KEY,以及CHECK约束。 外部键 定义外部关键字的语法在各种RDBMS中都是相似的。在外部关键字中标明的列数和每一列的数据类型必须和REFERENCES子句相匹配。一个输入到列中的非空的值必须在REFERENCES子句中定义表和列中存在,并且被提及的表的列必须有一个PRIMARY
KEY或者UNIQUE约束。 Microsoft SQL
Server约束提供了在同一个数据库中引用表的能力。要实现在数据库范围的应用完整性,可以使用基于表的触发器。 Oracle和SQL
Server都支持自引用表,这种表中有对同一个表的一列或几列的引用。例如,CLASS表中的prereq列可以引用CLASS表中的ccode列以确保一个有效的课程编号是作为一个子句的先决条件输入的。 在Oracle中实现层叠式的删除和修改是使用CASCADE DELETE子句,而SQL
Server用表触发器来实现同样的功能。如果需要了解更多的信息,请参看本章后面的“SQL语言支持”部分。 用户定义的完整性 用户定义的完整性允许你定义特定的商业规则,该规则不属于其他完整性的范畴。 存储过程 Microsoft SQL Server存储程序用CREATE
PROCEDURE语句来接受或者返回用户提供的参数。除临时存储程序以外,存储程序是在当前数据库中创建的。下表显示了Oracle和SQL
Server的语法。 Oracle Microsoft SQL
CREATE OR REPLACE PROCEDURE
[user.]procedure CREATE PROC[EDURE]
procedure_name
[;number] 在SQL
Server中,临时存储程序是在tempdb数据库中通过在procedure_name前加上数字标记来创建的。加一个数字标记(#procedure_name)表示是一个本地临时存储程序,加两个数字标记(##procedure_name)表示是一个全局临时程序。 一个本地临时程序只能被创建它的用户使用。执行本地临时程序的许可不能授予其他用户。本地临时程序在用户会话结束时自动删除。 一个全局的临时程序可以被所有的SQL
Server用户使用。如果一个全局临时程序被创建了,所有的用户都可以访问它,并且不能显式的撤回许可。全局临时程序在最后一个用户会话结束的时候自动删除。 SQL Server存储程序可以有最多32级嵌套。嵌套层数在被调用的程序开始执行时增加,在被调用的程序结束运行时减少。 下面的例子说明了怎样用一个Transact-SQL存储程序来代替一个Oracle的PL/SQL封装函数。Transact-SQL的版本更简单一些,因为SQL
Server的返回结果的能力是在一个存储程序中直接用SELECT语句设置的,不需要使用游标。 Oracle Microsoft SQL
CREATE OR REPLACE PACKAGE
STUDENT_ADMIN.P1 AS ROWCOUNT
NUMBER :=0; CREATE
PROCEDURE EXCEPTION SQL Server不支持与Oracle包或者函数相似的构造,也不支持在创建存储程序时的CREATE OR REPLACE选项。 延迟存储过程的执行 Microsoft SQL
Server提供了WAITFOR,允许开发人员给定一个时间,时间段,或者事件来触发一个语句块、存储程序或者事务的执行。这是Transact-SQL对于Oracle中dbms_lock_sleep的等价。 WAITFOR {DELAY 'time' | TIME 'time'} 指示Microsoft SQL Server等待直到给定的时间过去以后再执行,最多可以到24小时。 在这里 DELAY 指示Microsoft SQL Server等待,直到给定数量的时间过去以后才执行,最多可以设置到24小时。 'time' 需要等待的时间,时间可以是任何可接受的datetime数据类型的格式,或者可以作为一个本地变量给出。但是,不能指定datetime值的日期部分。 TIME 指示SQL Server等到指定的时间 例如: BEGIN WAITFOR TIME
'22:20' EXECUTE
update_all_stats END 指定存储程序中的参数 要在一个存储程序中指定一个参数,可以使用下面给出的语法。 Oracle Microsoft SQL
Varname datatype {@parameter data_type} [VARYING]
触发器(Triggers) Oracle和Microsoft SQL Server都有触发器,但它们在执行上有些不同。 描述 Oracle Microsoft SQL Server 每表可以有的触发器数 无限制 无限制 在INSERT, UPDATE, DELETE之前执行触发器 是 否 在INSERT, UPDATE, DELETE之后执行触发器 是 是 语句级触发器 有 有 行级触发器 有 无 在执行之前检查约束 是,除非触发器被取消 是。另外,这是DTS(Data Transformation Services)中的一个选项 在一个UPDATE或者DELETE触发器中提交旧的或者以前的值 :old DELETED.column 在INSERT触发器中提交新值 :new INSERTED.column 取消触发器 ALTER TRIGGER DTS中的选项 DELETED和INSERTED是SQL
Server为触发器创建的概念上的表。该表在结构上同触发器定义于其上的表相似,并且保存了可能被用户的行动改变的旧的或者新的行中的值。该表将跟踪在Transact-SQL中的行一级的变化。这些表提供了与Oracle中的行级别的触发器同样的功能。当一个INSERT、UPDATE、或者DELETE语句在SQL
Server中执行的时候,行被加入到触发器表中,而且是同时加入到INSERTED和DELETED表中。 INSERTED和DELETED表同触发器表是一样的。它们有同样的列名和数据类型。例如,如果在GRADE表中放置一个触发器,那么INSERTED和DELETED就有这样的结构。 GRADE INSERTED DELETED SSN CHAR(9) SSN CHAR(9) SSN CHAR(9) INSERTED和DELETED表可以被触发器检查以确定要执行什么样的触发器行动。INSERTED表同INSERT和UPDATE语句一起使用。DELETED表则和DELETE以及UPDATE语句一起使用。 UPDATE语句使用INSERTED和DELETED表,这是因为进行UPDATE操作时,SQL
Server总是要删除旧的行,填入新的行。因此,执行UPDATE时,INSERTED表中的行总是DELETED表中的行的副本。 下面的例子使用INSERTED和DELETED表来代替PL/SQL中的行级别的触发器。一个完全的外部接合点被用来查询任意表中的所有行。 Oracle Microsoft SQL Server
CREATE TRIGGER
STUDENT_ADMIN.TRACK_GRADES :OLD.GRADE, :NEW.SSN,
:NEW.CCODE,
:NEW.GRADE), CREATE TRIGGER
STUDENT_ADMIN.TRACK_GRADES 你可以只在当前数据库中创建一个触发器,你也可以引用当前数据库之外的对象。如果你使用所有者名称来修饰触发器,那么就用同样的方法来修饰表名。 触发器可以最多嵌套32级。如果一个触发器改变了某个表,而该表有另外一个触发器,则第二个触发器是活动的,可以调用第三个触发器,如此类推。如果链上的任何触发器引起了死循环,则嵌套级别溢出,该触发器被取消。此外,如果某表结果上的一行上的一个更新触发器同时是另一行的更新,那么更新触发器将只执行一次。 Microsoft SQL Server的公布引用完整性(declarative referential
integrity,DRI)没有提供跨数据库的引用完整性定义。如果需要跨数据库的完整性,可以使用触发器。 下面的语句在Transact-SQL触发器中是不被允许的。 |