把Oracle数据库移植到Microsoft SQL Server 7.0(3)
关键词:Sql Server, Oracle
索引
Microsoft SQL Server提供了分簇和未分簇的索引结构。这些索引是由来自于一个叫做B-tree的树型结构中
的页构成的(同Oracle中的B-tree索引结构相似)。起始页("根"级)说明了表中值的范围。"根"级页
中的每一个范围指向其他页(判断节点),该节点包含了表中值的更小的范围。以此类推,该节点又可以指
向其他的判断节点,这样就缩小了搜索的范围。树型结构的最后一级叫做"叶"级。
分簇的索引
分簇的索引在Oracle中是以索引组织表的形式实现的。一个分簇的索引是一个物理的包含在一个表中的索引。
表和索引分享同一块存储空间。分簇的索引按索引顺序物理的重排数据行,建立起中间判断节点。索引的
"叶"页包含了真实的表数据。这个结构允许每个表只有一个分簇的索引。Microsoft SQL Server为表自动
的创建一个分簇的索引,无论该表设置了PRIMARY KEY还是UNIQUE约束。分簇的索引对下面这些是有用的:
主键(Primary keys)
不能被更新的列。
返回一个值的范围的查询,使用诸如BETWEEN、>、>=、<、以及<=这样的操作符,例如:
SELECT * FROM STUDENT WHERE GRAD_DATE
BETWEEN '1/1/97' AND '12/31/97'
返回一个大的结果集合的查询:
SELECT * FROM STUDENT WHERE LNAME = 'SMITH'
被用做排序操作的列(ORDER BY、GROUP BY)
例如,在STUDENT表上,在ssn的主键上包含一个未分簇的索引是很有用的,而分簇的索引可以在lname、
fname(last name、first name)上创建,因为这是一种常用的区分学生的方法。
分布表上的更新行为可以防止出现"热点"。热点通常是由于多个用户向一个有上升键的表中填充而引起
的。这样的情景经常导致行级别的锁定。
删除和重建一个分簇的索引在SQL Server中是一种很普通的重新组织表的技术。这是一种确保数据页在磁
盘上是连续的以及重建表中的一些可用空间的简单的方法。这同Oracle中导出、删除以及导入一个表是很
相似的。
一个SQL Server分簇的索引与Oracle的簇在根本上是不一样的。一个Oracle的簇。一个Oracle的簇是两个
或者更多的表的物理集合,它们分享同一个数据块,使用一个公共的列来作为簇键。SQL Server没有与
Oracle簇相似的结构。
作为一个普遍的原则,在表上定义一个分簇的索引将提高SQL Server的性能并且加强空间管理。如果你
不知道对于给定表的查询和更新模式,你可以在主键上创建一个分簇的索引。
下表摘录自示例应用程序的源代码。请注意SQL Server"簇"化索引的使用。
Oracle Microsoft SQL
CREATE TABLE STUDENT_ADMIN.GRADE (
SSNCHAR(9) NOT NULL,
CCODEVARCHAR2(4) NOT NULL,
GRADEVARCHAR2(2) NULL,
CONSTRAINT GRADE_SSN_CCODE_PK
PRIMARY KEY (SSN, CCODE)
CONSTRAINT GRADE_SSN_FK
FOREIGN KEY (SSN) REFERENCES
STUDENT_ADMIN.STUDENT (SSN),
CONSTRAINT GRADE_CCODE_FK
FOREIGN KEY (CCODE) REFERENCES
DEPT_ADMIN.CLASS (CCODE)
) CREATE TABLE STUDENT_ADMIN.GRADE (
SSNCHAR(9) NOT NULL,
CCODEVARCHAR(4) NOT NULL,
GRADEVARCHAR(2) NULL,
CONSTRAINT
GRADE_SSN_CCODE_PK
PRIMARY KEY CLUSTERED (SSN, CCODE),
CONSTRAINT GRADE_SSN_FK
FOREIGN KEY (SSN) REFERENCES
STUDENT_ADMIN.STUDENT (SSN),
CONSTRAINT GRADE_CCODE_FK
FOREIGN KEY (CCODE) REFERENCES
DEPT_ADMIN.CLASS (CCODE)
)
未分簇的索引
在未分簇的索引中,索引数据和表数据在物理上是分开的,并且表中的行并不是按顺序存储在索引中的。
你可以把Oracle索引定义移植到Microsoft SQL Server未分簇的索引定义上(就像在下表中显示的一样)。
可是,考虑到性能的缘故,你可能希望选择表的其中一个索引把它创建为分簇的索引。
Oracle Microsoft SQL
CREATE INDEX
STUDENT_ADMIN.STUDENT_
MAJOR_IDX
ON STUDENT_ADMIN.STUDENT (MAJOR)
TABLESPACE USER_DATA
PCTFREE 0
STORAGE (INITIAL 10K NEXT 10K
MINEXTENTS 1 MAXEXTENTS
UNLIMITED) CREATE NONCLUSTERED INDEX
STUDENT_MAJOR_IDX
ON USER_DB.STUDENT_
ADMIN.STUDENT (MAJOR)
索引语法和命名
在Oracle中,一个索引的名字在一个用户账号中是唯一的。在In Microsoft SQL Server,一个索引的名
字在一个表名中必须是唯一的,但是不必在用户名和数据库名中唯一。因此,在SQL Server中创建或者删
除索引时,你必须说明表名和索引名。另外,SQL Server的DROP INDEX语句可以一次删除多个索引。
Oracle Microsoft SQL
CREATE [UNIQUE] INDEX [schema].index_name
ON [schema.]table_name (column_name
[, column_name]...)
[INITRANS n]
[MAXTRANS n]
[TABLESPACE tablespace_name]
[STORAGE storage_parameters]
[PCTFREE n]
[NOSORT]
DROP INDEX ABC;
CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED]
INDEX index_name ON table (column [,…n])
[WITH
[PAD_INDEX]
[[,] FILLFACTOR = fillfactor]
[[,] IGNORE_DUP_KEY]
[[,] DROP_EXISTING]
[[,] STATISTICS_NORECOMPUTE]
]
[ON filegroup]
DROP INDEX USER_DB.STUDENT.DEMO_IDX, USER_DB.GRADE.DEMO_IDX
索引数据存储参数
Microsoft SQL Server功能选项中的FILLFACTOR选项在很多方面与Oracle中的PCTFREE变量相似。当表的
尺寸增加的时候,索引页也相应改变以容纳新的数据。索引必须自己进行重新组合以容纳新的数据。只有
在创建索引的时候,才使用填充参数百分比,而且在这之后也不加以维护。
FILLFACTOR选项(0~100)控制着在创建索引时应该留下多少空间。如果没有表明参数,就使用缺省
参数,该参数是0,表示将完全填充索引的"叶"页,并且在每个判断节点为至少一个条目留下空间(如
果有两个条目,则表示是一个不唯一的"簇"化索引)。
一个较低的填充因数将会减少索引页的分裂,但是会增加B-tree结构的层数。较高的填充因数能更有效的
使用索引页空间,只需要较少的磁盘I/O来访问索引数据,并且将会减少B-tree结构的层数。
PAD_INDEX选项表示,填充因数也将应用到判断节点页上,就象要用在索引的数据页上一样。
虽然在 Oracle中可能需要调整PCTFREE参数以优化性能。但是在CREATE INDEX语句中很少使用FILLFACTOR
参数。填充因数是为性能优化而提供的。但是它仅仅在一个表上为已有数据创建索引时才有用,并且只有在
你能精确的预测数据在未来的变化时才有用。
如果你将Oracle中的PCTFREE参数设为0,可以考虑将它设为100。这在表中不会发生数据输入和修改(
只读表)时是很有用的。如果填充因数设为100,服务器将创建这样一个索引,它的每一页都是完全填满
的。
忽略重复的关键字
无论在Oracle还是在Microsoft SQL Server中,用户都不能在一个或者一些唯一索引的列中输入重复的值。
这样做将会产生一个错误消息。然而,SQL Server允许开发人员选择INSERT或者UPDATE语句将如何处理这个
错误。
如果在CREATE INDEX语句中使用了IGNORE_DUP_KEY,并且执行了一个创建重复的关键字的INSERT或者UPDATE
语句,SQL Server将给出一个警告信息,并且忽略重复行。如果没有使用IGNORE_DUP_KEY,SQL Server将给
出一个错误信息,并且后滚整个INSERT语句。如果需要了解关于这个选项的更多信息,请参看SQL Server联
机手册。
使用临时表
一个Oracle应用程序也许必须创建一个暂时存在的表。应用程序必须确保在某个时候删除所有为此目的创建
的表。如果应用程序不这样做,那么表空间将很快变得混乱,难以管理。
Microsoft SQL Server提供了临时表数据库对象,这个表就是为上面提到的目的创建的。这样的表总是在
tempdb数据库中创建的。表的名字决定了该表在tempdb数据库中要存在多长时间。
表名 描述
#table_name 这个本地临时表只在用户会话或者创建它的过程的生命期内存在。在用户退出登录或者创建
它的过程完成以后,该表自动删除。该表不能在多个用户之间共享。其它数据库用户不能访问该表。在该
表上不能赋予或者撤消许可。
##table_name 该表也典型的存在于用户会话或者创建它的过程的生命期内。但该表可以被多个用户共享。
在最后一个引用它的用户会话断开以后,该表自动删除。所有其它数据库的用户都可以访问该表。在该表上
不能赋予或者撤消许可。
可以为临时表定义索引。但是只能在那些在tempdb中显明的创建的表上创建视图,这些表的名字前不加#或
者##前缀。下面的例子显示了一个临时表和相应的索引的创建。当用户退出的时候,表和索引就自动删除了。
SELECT SUM(ISNULL(TUITION_PAID,0)) SUM_PAID, MAJOR INTO #SUM_STUDENT
FROM USER_DB.STUDENT_ADMIN.STUDENT GROUP BY MAJOR
CREATE UNIQUE INDEX SUM STUDENT IDX ON #SUM STUDENT (MAJOR)
在你的程序代码中使用临时表,你可以发现它的好处。
数据类型
同Oracle比起来,Microsoft SQL Server在数据库类型的选择上更强大。在Oracle和SQL Server数据类型
之间有很多可能的转换方式。我们建议你使用DTS向导来自动创建新的CREATE TABLE语句。需要的时候,你
还可以修改它。
Oracle Microsoft SQL
CHAR 推荐使用char。 char 类型的列比varchar列的访问速度要稍微快一点,因为char列使用一个固定的存
储长度。
VARCHAR2
和 LONG varchar 或者 text. (如果在你的Oracle列中数据值的长度小于或等于8000 bytes ,使用varchar;
否则,你必须使用text。)
RAW 和
LONG RAW varbinary 或者 image. (如果在你的Oracle列中数据值的长度小于或等于8000 bytes,使用
varbinary;否则,你必须使用image。)
NUMBER 如果整数在1到255之间, 使用tinyint.
如果整数在-32768到32767之间,使用smallint.
如果整数在-2,147,483,648到2,147,483,647之间,使用int.
如果你需要浮点型的数,使用numeric (精确且可以定标).
注意: 不要使用float或者real, 因为可能会发生截断(Oracle NUMBER和 SQL Server numeric 不会截断).
如果你不确定,使用numeric; 它同Oracle NUMBER数据类型非常相似。
DATE datetime.
ROWID 使用identity列类型
CURRVAL, NEXTVAL 使用identity列类型, 以及@@IDENTITY, IDENT_SEED(), 和IDENT_INCR() 函数。
SYSDATE GETDATE().
USER USER.
使用Unicode数据
Unicode规范定义了一个编码方案,该方案使用单一编码方式为全世界范围内业务上使用的所有字符编码。所
有的计算机都能使用单一的Unicode编码把Unicode数据中的位模式转换成为字符。这个方案确保了在所有的
计算机上,同样的位模式转换为同样的字符。数据可以自由的从一个数据库或者一台计算机传送到另一个上
面,而不用考虑接受系统能否把位模式正确的转换成字符。
使用一个字节来表示字符的方法有一个问题,就是这种数据类型只能表示256个字符。这样就为不同的语
言产生了多个编码规范(或者叫做代码页)。这样做也不可能处理日文或者韩文这样有上千个字符的语言。
Microsoft SQL Server把在SQL Server中安装了代码页的字符的位模式转换成char,varchar,或者text类型
的列。客户端则使用操作系统安装的代码页来解释字符的位模式。现在有很多不同的代码页。有些字符只在
某些代码页上才有,在别的代码页上就没有。某些字符在某些代码页上定义为一种位模式,在另外一些代码
页上又定义为另一种位模式。如果你要建立一个必须处理各种语言的国际系统时,为那些满足语言要求或者
多个国家的计算机挑选代码页就变得非常困难。同样,在和一个使用不同代码页的系统连接时,确保每一台
计算机都能正确的实现字符转换也非常困难。
Unicode规范使用双字节编码方案解决了这个问题。使用双字节编码,就有足够的空间来覆盖最广泛使用的商
业语言了。因为所有的Unicode系统都采用同样的位模式来代表所有的字符,在从一个系统转移到另一个系统
的时候,就不会发生字符转换不正确的问题了。
在SQL Server中,nchat,nvarchar和ntext数据类型支持Unicode数据。如果需要了解关于SQL Server数据类
型的更多信息,请参看SQL Server联机手册。
用户定义数据类型
可以为model数据库或者单用户数据库创建用户定义数据类型。如果是为model定义用户定义数据类型,则该
数据类型可以被定义之后所有新创建的用户数据库使用。用户定义数据类型是通过sp_addtype系统存储程序
来定义的。如果需要了解更多信息,请参看SQL Server联机手册。
你可以在CREATE TABLE和ALTER TABLE语句中使用用户定义数据类型,并且为它绑定缺省方式和规则。如果在
表的创建过程使用用户定义数据类型时显明的定义了nullability,则它比在数据定义时定义的nullability
优先级高。
下例显示了如何创建用户定义数据类型。参数是用户类型名字,数据类型和nullability。
sp_addtype gender_type, 'varchar(1)', 'not null'
go
这个能力对于解决与Oracle表创建脚本移植到SQL Server上相关的问题是很有用的。例如,要增加一个Oracle
的DATE数据类型是非常简单的。
sp_addtype date, datetime
这个功能不能用在那些需要变长度的数据类型上,例如Oracle数据类型NUMBER。如果这样做,系统将会返回
一个错误信息,告诉你需要标明数据长度。
sp_addtype varchar2, varchar
Go
Msg 15091, Level 16, State 1
You must specify a length with this physical type.
Microsoft timestamp列
timestamp列使得BROWSE模式修改和游标修改操作更有效。timestamp是这样一个数据类型,含有timestamp
列的行有输入或者修改操作时,该数据类型自动修改。
timestamp列中的值不是按照实际的日期和时间存储的,而是作为binary(8)或者varbinary(8)存储的,这个
值表示表中一行发生的事件的频率。一个表只能有一个timestamp列。
如果要了解更多信息,请参看SQL Server联机手册。
对象级许可
Microsoft SQL Server对象特权可以向任何其他数据库用户、数据库组以及public角色授予、拒绝授予、和
撤消。SQL Server不允许对象的所有者授予其他用户、组或者public角色ALTER TABLE和CREATE INDEX特权
,这一点与Oracle不同。这些特权必须被对象所有者保留。
GRANT语句创建一个安全系统的入口许可,该许可允许当前数据库中的一个用户可以操作当前数据库中的数
据,或者执行特定的Transact-SQL语句。GRANT语句的语法在Oracle和SQL Server中是一样的。
DENY语句在安全系统中创建一个条目,拒绝当前数据库中的一个安全账号的许可,并且禁止该安全账号继承
自该账号所属的组或者角色成员的许可。Oracle中没有DENY语句。REVOKE语句清除以前授予给当前数据库中
一个用户的许可或者拒绝其许可。
Oracle Microsoft SQL
GRANT {ALL [PRIVILEGES][column_list] | permission_list [column_list]}
ON {table_name [(column_list)]
| view_name [(column_list)]
| stored_procedure_name}
TO {PUBLIC | name_list }
[WITH GRANT OPTION] GRANT
{ALL [PRIVILEGES] | permission[,…n]}
{
[(column[,…n])] ON {table | view}
| ON {table | view}[(column[,…n])]
| ON {stored_procedure | extended_procedure}
}
TO security_account[,…n]
[WITH GRANT OPTION]
[AS {group | role}]
REVOKE [GRANT OPTION FOR]
{ALL [PRIVILEGES] | permission[,…n]}
{
[(column[,…n])] ON {table | view}
| ON {table | view}[(column[,…n])]
| {stored_procedure | extended_procedure}
}
{TO | FROM}
security_account[,…n]
[CASCADE]
[AS {group | role}]
DENY
{ALL [PRIVILEGES] | permission[,…n]}
{
[(column[,…n])] ON {table | view}
| ON {table | view}[(column[,…n])]
| ON {stored_procedure | extended_procedure}
}
TO security_account[,…n]
[CASCADE]
如果需要了解关于对象级许可的更多信息,请参看 SQL Server联机手册。
在Oracle中,REFERENCES特权只能授予用户。SQL Server则允许把该特权授予数据库用户和数据库组。
INSERT、UPDATE、DELETE和SELECT特权的授予在Oracle和SQL Server中以同样的方式处理。
加强数据完整性和商业规则
加强数据完整性确保数据库中数据的质量。规划表时重要的两个步骤是鉴定列中值的有效性和如何加强列
中数据的完整性。数据完整性可以分为四类,它们是以不同的方式进行加强的。
完整性类型 如何强制
Entity integrity PRIMARY KEY constraint
UNIQUE constraint
IDENTITY property
Domain integrity Domain DEFAULT definition
FOREIGN KEY constraint
CHECK constraint
Nullability
Referential integrity Domain DEFAULT definition
FOREIGN KEY constraint
CHECK constraint
Nullability
User-defined integrity All column- and table-level constraints in CREATE TABLE
Stored procedures
Triggers
实体完整性(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
(DEPT VARCHAR2(4) NOT NULL,
DNAME VARCHAR2(30) NOT NULL,
CONSTRAINT DEPT_DEPT_PK
PRIMARY KEY (DEPT)
USING INDEX TABLESPACE
USER_DATA
PCTFREE 0 STORAGE (
INITIAL 10K NEXT 10K
MINEXTENTS 1 MAXEXTENTS UNLIMITED),
CONSTRAINT DEPT_DNAME_UNIQUE
UNIQUE (DNAME)
USING INDEX TABLESPACE USER_DATA
PCTFREE 0 STORAGE (
INITIAL 10K NEXT 10K
MINEXTENTS 1 MAXEXTENTS
UNLIMITED)
) CREATE TABLE USER_DB.DEPT_ADMIN.DEPT
(DEPTVARCHAR(4) NOT NULL,
DNAMEVARCHAR(30) NOT NULL,
CONSTRAINT DEPT_DEPT_PK
PRIMARY KEY CLUSTERED (DEPT),
CONSTRAINT DEPT_DNAME_UNIQUE
UNIQUE NONCLUSTERED (DNAME)
)
增加和清除约束
使约束失效可以改善数据库性能,并且使数据复制过程更加流畅。例如,当你在一个远程站点上重建或者
复制表中的数据时,你不用重复约束检查,因为数据的完整性是在它原来输入数据库时就检查过的。你可
以编制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
( Empid int IDENTITY (1,1), Employee_Name varchar(60),
CONSTRAINT Emp_PK PRIMARY KEY (Empid)
)
If increment interval is 5:
CREATE TABLE new_employees
( Empid int IDENTITY (1,5), Employee_Name varchar(60),
CONSTRAINT Emp_PK PRIMARY KEY (Empid)
)
每个表拥有的标识列 一个
允许空值 否
使用缺省约束、值 不能使用.
强制唯一 是
在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 (
SSN CHAR(9) NOT NULL,
FNAME VARCHAR2(12) NULL,
LNAME VARCHAR2(20) NOT NULL,
GENDER CHAR(1) NOT NULL
CONSTRAINT
STUDENT_GENDER_CK
CHECK (GENDER IN ('M','F')),
MAJOR VARCHAR2(4)
DEFAULT 'Undc' NOT NULL,
BIRTH_DATE DATE NULL,
TUITION_PAID NUMBER(12,2) NULL,
TUITION_TOTAL NUMBER(12,2) NULL,
START_DATE DATE NULL,
GRAD_DATE DATE NULL,
LOAN_AMOUNT NUMBER(12,2) NULL,
DEGREE_PROGRAM CHAR(1)
DEFAULT 'U' NOT NULL
CONSTRAINT
STUDENT_DEGREE_CK CHECK
(DEGREE_PROGRAM IN ('U', 'M', 'P', 'D')),
... CREATE TABLE USER_DB.STUDENT
_ADMIN.STUDENT (
SSN CHAR(9) NOT NULL,
FNAME VARCHAR(12) NULL,
LNAME VARCHAR(20) NOT NULL,
GENDER CHAR(1) NOT NULL
CONSTRAINT STUDENT_GENDER_CK
CHECK (GENDER IN ('M','F')),
MAJOR VARCHAR(4)
DEFAULT 'Undc' NOT NULL,
BIRTH_DATE DATETIME NULL,
TUITION_PAID NUMERIC(12,2) NULL,
TUITION_TOTAL NUMERIC(12,2) NULL,
START_DATE DATETIME NULL,
GRAD_DATE DATETIME NULL,
LOAN_AMOUNT NUMERIC(12,2) NULL,
DEGREE_PROGRAM CHAR(1)
DEFAULT 'U' NOT NULL
CONSTRAINT STUDENT_DEGREE_CK
CHECK
(DEGREE_PROGRAM IN ('U', 'M',
'P','D')),
...
关于用户定义规则和缺省(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。
如果任何会话设置为ON (用SET打开), 则:
如果ANSI_NULL_DFLT_ON是ON, 则指定为NULL.
如果ANSI_NULL_DFLT_OFF是ON, 则指定为NOT NULL.
如果任何数据库设置被修改过(用sp_dboption 系统存储过程修改), 则:
如果ANSI null default是true, 则指定为NULL.
如果ANSI null default是false, 则指定为NOT NULL
NULL/NOT NULL
没有定义 当没有显明的定义时(ANSI_NULL_DFLT选项一个都没有设定),会话将被修改,并且数据库被设定
为缺省(ANSI null default是false),然后SQL Server指定它为NOT NULL。