科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航



ZDNet>软件频道>数据库-zhiding>把Oracle数据库移植到Microsoft SQL Server 7.0

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

  应用程序的移植似乎非常复杂。在不同的关系数据管理系统之间有太多的结构差异。用来描述Oracle结构的   用词和术语通常与该词在Microsoft SQL Server中的意思完全不同。另外。

来源:中国IT实验室 2007年10月11日

关键字:ORACLE 数据库 备份


  应用程序的移植似乎非常复杂。在不同的关系数据管理系统之间有太多的结构差异。用来描述Oracle结构的
  用词和术语通常与该词在Microsoft SQL Server中的意思完全不同。另外,Oracle和SQL Server都对SQL-92
  标准做了许多自有的扩展。
  
  从一个应用程序开发人员的观点来看,Oracle和SQL Server是以相似的方法来管理数据的。在Oracle和SQL
  Server之间有着重大的内部区别,但是如果管理得当,可以把这些区别对移植的影响减到最小。
  
  SQL语言扩展
  开发人员面临的最重要的移植问题是执行SQL-92语言标准和每一个关系数据管理系统提供的语言扩展。有一
  些开发人员只使用标准的SQL语法,喜欢尽可能的保持他们的程序代码的普遍性。通常,这种方法把程序代
  码限制在SQL-92标准的登录级别(entry-level)上,而这个级别是被许多的数据库产品实现了的,包括
  Oracle和SQL Server。
  
  这种方法将会产生一些不必要的程序代码复杂性而且还会对程序的性能造成很大的影响。例如,Oracle的
  DECODE函数是一个非标准的SQL扩展。Microsoft SQL Server的CASE表达式是一个超越了登录级别的SQL-92
  扩展,而且在所有其他的数据库产品中都没有实现。
  
  Oracle的DECODE和SQL Server的CASE都是可选的,你可以不用这两个函数而实现它们的功能,而这需要从关
  系数据管理系统中提取更多的数据。
  
  还有,对SQL语言的程序扩展也会造成困难。Oracle的PL/SQL和SQL Server的Transact-SQL语言在函数上是
  相似的,但是在语法上不同。在两种数据库和程序扩展中间没有明确的对称性。因此,你可能会决定不使用
  想程序和触发器这样的存储的程序。这是很不幸的,因为它们提供了别的任何方式都无法实现的性能和安全
  性上的优点。
  
  私有开发接口的使用带来了新的问题。用Oracle OCI(Oracle Call Interface)进行程序转换通常需要很多
  资源。开发一个可能用到多个关系数据管理系统的应用程序,最好是考虑使用开放数据库连接(Open
  Database Connectivity,ODBC)接口。
  
  ODBC
  ODBC是为同多个数据库管理系统协同工作而设计的。ODBC提供了一个一致的应用程序编程接口(application
   programming interface,API),该接口使用一个针对数据库的驱动程序同不同的数据库协同工作。
  
  一致的应用程序编程接口意味着程序用来建立连接、执行命令以及获取结果的函数是一样的,无论该程序是和
  Oracle还是SQL Server对话。
  
  ODBC同时还定义了一个标准化的调用级别的接口并且针对那些不同数据库里完成同样任务但语法不同的SQL函
  数使用标准的出口次序。ODBC驱动器可以自动的把这个ODBC语法转化为Oracle或者SQL Server的本地语法,
  这个过程不需要对程序代码做任何的修订。在某些情况下,最好的方法是编写一个程序并且让ODBC在运行时
  间执行转换处理。
  
  ODBC并不是一个万能的可以针对任何数据库实现完全独立的、完整功能和高性能的解决方案。不同数据库和
  第三方经销商提供了对ODBC不同级别的支持。一些驱动器仅仅实现了核心的API函数,这些函数映射了顶层或
  者其他接口库。其他一些驱动器,例如Microsoft SQL Server的驱动器,在一个本地的、高性能的驱动器中
  提供了完整的2级支持。
  
  如果一个程序仅使用核心的ODBC API,它很可能会丢弃某些数据库的特征和性能。此外,并不是所有的本地
  SQL扩展都可以在ODBC出口次序中描述的(例如Oracle的DECODE和SQL Server的CASE表达式)。
  
  另外,书写SQL语句来利用数据库优化器是意见很自然的事情。但是在Oracle中用来扩展数据库性能的技术和
  方法在Microsoft SQL Server 7.0中不一定是最好的。ODBC接口并不能把一个系统所用的技术翻译为另一个
  系统的技术。
  
  ODBC并不影响一个应用程序使用数据库专有的特征和调整来提高性能,但是应用程序需要某些数据库专有的
  代码部分。ODBC使得在多个数据库间保持程序结构和多数程序代码一致变得容易。
  
  OLE DB
  OLE DB是下一代数据访问技术。Microsoft SQL Server 7.0利用包含在其自身的组件之中的OLE DB。这样,
  应用程序开发人员可以考虑使用OLE DB来进行新的SQL Server 7.0开发。微软在SQL Server 7.0中还提供了
  支持Oracle 7.3的OLE DB。
  
  OLE DB是微软用来管理跨组织的数据的战略性的系统级编程接口。OLE DB是在ODBC特征上建立的具有开放性
  的设计。ODBC是设计来访问相关的数据库的,而OLE DB则是设计来访问相关的或者不相关的信息源,例如主
  机上的ISAM/VSAM和分层数据库,电子邮件和文件系统存储,文本、图像和地理数据以及定制的业务对象。
  
  OLE DB了一组COM接口以压缩不同的数据库管理服务,同时还允许创建软件组件来实现这些服务.OLE DB组件
  包含了数据提供者(保持和显露数据)、数据消费者(使用数据)以及服务组件(处理和传输数据,例如查
  询处理器和光标引擎)。
  
  OLE DB接口的设计目的是帮助实现组件的平滑集成,这样的话OLE DB组件提供商就可以迅速的向市场提供高
  质量的OLE DB组件了。此外、OLE DB还包含一座连接ODBC的桥梁,如此就可以为今天可以得到的大量的ODBC
  相关的数据库驱动程序继续提供支持了。
  
  本文的组织方式
  为了帮助你一步一步的实现从Oracle到SQL Server的转换,本文的每一部分都有一个关于Oracle7.3和
  Microsoft SQL Server 7.0的不同之处的概述。同时还包括转换的考虑,SQL Server 7.0的优势以及多个实
  例。
  
  结构和术语
  作为成功移植的开始,你应该掌握Microsoft SQL Server 7.0所用的基本的结构和术语。这一部分中的许多
  例子都是从本文包含的Oracle和SQL Server应用程序中截取下来的。
  数据库的定义
  
  在Oracle中,数据库是指整个Oracle RDBMS环境,并且包含以下组件。
  
  Oracle数据库处理过程和数据缓存(实例)。
  
  
  包含一个集中的系统目录的SYSTEM表空间。
  DBA定义的其它表空间(可选的)。
  两个或者多个Redo日志。
  存档的Redo日志(可选)
  各种其它文件(控制文件、Init.ora等等)。
  一个Microsoft SQL Server数据库提供了数据、应用程序以及安全机制的逻辑区分,更像一个表空间(
  tablespaces)。正如Oracle支持多个表空间,SQL Server也支持多个数据库。表空间也用来提供数据的物
  理放置,SQL Server通过文件组(filegroups)来提供同样的功能。
  
  Microsoft SQL Server将缺省的安装下列数据库。
  
  model数据库是所有新建用户数据库的模板。
  Tempdb数据库跟Oracle中的临时表空间很相象,都是用来进行临时的工作储存以及排序操作。不同的是,当
  用户退出登录时,Microsoft SQL Server自动删除其创建的临时表空间。
  Msdb数据库支持SQL Server代理以及其预定的工作、警报和复制信息。
  Northwind和pubs数据库是用于培训的实例数据库。
  如果想获得缺省数据库的更多信息,请参看SQL Server联机图书。
  数据库系统目录
  每个Oracle数据库都在一个集中系统目录(或者是数据字典(data dictionary))上运行,该目录存在于
  SYSTEM表空间中。而每个Microsoft SQL Server 7.0数据库都维护一个自己的系统目录,该目录包含下列
  信息:
  数据库对象(表、索引、存储程序、视图、触发器等等)。
  
  约束(Constraints)。
  用户和许可。
  用户定义数据类型。
  复制定义。
  数据库所用的文件。
  SQL Server同时在master数据库中保存一个集中系统目录,该目录包含系统目录和每个数据库的某些信息:
  
  数据库名和每个数据库的初始文件位置。
  SQL Server登录账号。
  系统消息。
  数据库配置值。
  远程和/或已连接的服务器。
  当前活动信息。
  系统存储过程。
  
  像Oracle中的SYSTEM表空间一样,SQL Server的master数据库也必须能访问任何其他数据库。同样,对数
  据库做了任何重大的改变以后,通过备份master数据库来防止失败是很重要的。数据库管理员也应该能够
  为组成master数据库的文件做镜象。
  
  物理和逻辑存储结构(Physical and Logical Storage Structures)
  Oracle RDBMS是由表空间组成的,而表空间又是由数据文件组成的。表空间数据文件被格式化为内部的块
  单位。块的大小,是由DBA在Oracle第一次创建的时候设置的,可以在512到8192个字节的范围内变动。当
  一个对象在Oracle表空间中创建的时候,用户用叫做长度的单位(初始长度((initial extent)、下一个
  长度(next extent)、最小长度(min extents)、以及最大长度(max extents))来标明该对象的空间
  大小。一个Oracle长度的大小可以变化,但是要包含一个由至少五个连续的块构成的链。
  
  Microsoft SQL Server在数据库级别使用文件组来控制表和索引的物理放置。文件组是一个或者多个文件的
  逻辑容器,一个文件组中的数据按比例填充属于该文件组的全部文件。
  如果没有显明的定义和使用文件组,数据库对象将放置在一个缺省的文件组中,该文件组是在数据库的创建
  过程中隐含定义的。文件组允许你进行下列操作:
  把大的表分布在多个文

查看本文来源


  安装和配置Microsoft SQL Server
  
  了解了Oracle和SQL Server之间基本结构上的差异以后,你就可以开始进行移植过程的第一步了。SQL Server
   Query Analyzer将用来运行下面的脚本:
  
   
  
  使用Windows NT基于软件的RAID或者基于硬件的RAID第五级来创建一个足够放下你的所有数据的逻辑驱动器。
  对空间的估算可以通过计算被Oracle系统、临时文件以及应用程序表空间占用的文件空间大小来进行。
  
  使用Windows NT基于软件的RAID或者基于硬件的RAID第一级创建一个第二逻辑驱动器来放事务日志。该驱动
  器的大小起码应该和在线恢复以及后滚表空间的总的大小一致。
  
  使用SQL Server Enterprise Manager创建一个和Oracle应用程序表空间名字一样的数据库。(示例应用程
  序使用的数据库名字叫做USER_DB)标明文件位置,使它们分别和你在第一步以及第二步中为数据和事务创
  建的磁盘位置一致。如果你使用多个Oracle表空间,不需要也建议你不要创建多个SQL Server数据库,RAID
  会自动为你分配的。
  创建SQL Server登录账号: USE MASTER
  EXEC SP_ADDLOGIN STUDENT_ADMIN, STUDENT_ADMIN
  
  EXEC SP_ADDLOGIN DEPT_ADMIN, DEPT_ADMIN
  
  EXEC SP_ADDLOGIN ENDUSER1, ENDUSER1
  
  GO
  
  
  为数据库添加角色: USE USER_DB
  EXEC SP_ADDROLE DATA_ADMIN
  
  EXEC SP_ADDROLE USER_LOGON
  
  GO
  
  
  为角色授予许可: GRANT CREATE TABLE, CREATE TRIGGER, CREATE VIEW,
  CREATE PROCEDURE TO DATA_ADMIN
  
  GO
  
  
  增加作为数据库用户账号的登录账号:
  EXEC SP_ADDUSER ENDUSER1, ENDUSER1, USER_LOGON
  EXEC SP_ADDUSER DEPT_ADMIN, DEPT_ADMIN, DATA_ADMIN
  
  EXEC SP_ADDUSER STUDENT_ADMIN, STUDENT_ADMIN, DATA_ADMIN
  
  GO
  
  
   
  
  定义数据库对象
  
  Oracle数据库对象(表、视图和索引)可以很容易的移植到Microsoft SQL Server上,这是因为两个数据
  库都基本遵循SQL-92标准,该标准承认对象定义。把Oracle SQL的表、索引和视图的定义转换为SQL Server
  的表、索引和视图的定义只需要做相对简单的语法改变。下表指出了Oracle和Microsoft SQL Server之间的
  数据库对象的某些不同之处。
  
  类别 Microsoft SQL Server Oracle
  列数 1024 254
  行尺寸 8060 byte, 外加16 byte用来指向每一个text或者image列 无限制 (每行只允许有一个long或者long
  raw)
  最大行数 无限制 无限制
  BLOB类型存储 行中存储一个16-byte 指针。数据存储在其他数据页。 每表一个long或者long raw。 必须在
  行的结尾。数据存储在行的同一个块里。
  分簇表索引 每表一个 每表一个(index-organized tables)
  未分簇的表索引 每表249 无限制
  在单一索引中的最大索引列数 16 16
  索引中列值的最大长度 900 bytes ? block
  表名约定 [[[server.]database.]owner.]
  table_name [schema.]table_name
  视图名约定 [[[server.]database.]owner.]
  table_name [schema.]table_name
  索引名约定 [[[server.]database.]owner.]
  table_name [schema.]table_name
  
   
  
  
  假设你是从一个Oracle脚本或者程序开始的,该脚本或者程序用来创建你的数据库对象。拷贝你的脚本或
  者程序并且进行如下修改。这些修改将在本部分的其他地方加以讨论。该例子是从示例应用程序脚本
  Oratable.sql和Sstable.sql中截取的:
  
  确保数据库对象标识遵循Microsoft SQL Server命名法则。你可能只需要修改索引的名字。
  修改数据存储参数使之能在SQL Server下工作。如果你使用RAID,就不需要任何存储参数了。
  修改Oracle约束定义使之能在SQL Server中工作。如果需要的话,创建一个触发器以支持外部键DELETE
   CASCADE语句。如果表跨数据库的话,使用触发器来增强外部键的关系。
  修改CREATE INDEX语句以利用分簇的索引。
  使用数据转换服务来创建新的CREATE TABLE语句。回顾该语句,注意Oracle数据类型是如何映射到SQL
  Server数据类型上的。
  清除所有的CREATE SEQUENCE语句。在CREATE TABLE或者ALTER TABLE语句中使用同等列来替换顺序的使用。
  如果需要的话,修改CREATE VIEW语句。
  清除所有对同义字的引用。
  评估对Microsoft SQL Server临时表的使用和其在你的应用程序中的用处。
  把所有的Oracle的CREATE TABLE…AS SELECT命令改为SQL Server的SELECT…INTO语句。
  评估潜在的对用户定义规则、数据类型和缺省的使用。
   
  
  数据对象标识符
  
  下表比较了Oracle和Microsoft SQL Server是如何处理对象标识符的。在许多情况下,当移植到SQL
  Server上时,你不需要改变对象的名字。
  
  Oracle Microsoft SQL 
  1-30 字符长度。
  数据库名称:最多8个字符长度。
  数据库连接名称:最多128个字符长度。 1-128 Unicode字符长度。
  临时表名称:最多116个字符。
  标识符的名称必须用:字母、包含文字数字的字符、或者字符_, $, 和 #开头 标识符名称可以用:字母
  数字字符、或者_开头,实际上可以用任何字符开头。
  如果标识符用空格开头,或者包含了不是_、@、#、或者$的字符,你必须用[](定界符)包围标识符名称
  
  如果一个对象用下面这些字符开头:
  @ 则表明该对象是一个本地变量。
  # 则该对象是一个本地临时对象。
  ## 则该对象是一个全局临时对象
  
  表空间名必须唯一. 数据库名必须唯一
  标识符名在用户账号(计划,Schema)范围内必须唯一。 标识符名在数据库用户账号范围内必须唯一
  列名在表和视图范围内必须唯一。 列名在表和视图范围内必须唯一。
  索引名在用户账号(Schema)范围内必须唯一。 索引名在数据库表名范围内必须唯一
  
   
  
  修饰表名
  
  当访问存在于你的用户账号中的表时,该表可以简单的通过未经限制的表名来选中。访问其他Oracle计划
  中的表就需要把该计划的名字作为前缀加到表名上,两者之间用点号(.)隔开。Oracle同义字可以提供
  更高的位置透明度。
  
  涉及到表时,Microsoft SQL Server采用一种不同的方法。因为一个SQL Server登录账号可以在多个数据
  库中用同一个名字创建一个表,所以采用下面的方法来访问表和视图:[[数据库名字]所有者名字]表名]
  
  用……访问一个表 Oracle Microsoft SQL Server
  你的用户账号 SELECT *
  FROM STUDENT SELECT * FROM USER_DB.STUDENT_
  ADMIN.STUDENT
  其他模式(schema) SELECT * FROM STUDENT_ADMIN.STUDENT SELECT * FROM OTHER_DB.STUDENT_
  ADMIN.STUDENT
  
   
  
  这是一些为Microsoft SQL Server表和视图命名的指导方针:
  
  使用数据库名字和用户名字是可选的。如果一个表只通过名字加以引用(例如,STUDENT),SQL Server在
  当前数据库中以当前用户帐号搜索该表。如果没有找到,就在数据库中寻找由dbo的保留用户名拥有的具有
  同样名字的对象。表名在同一个数据库中的同一个用户帐号下必须是唯一的。
  同一个SQL Server登录账号可以在多个数据库中拥有同样名字的表。例如,ENDUSER1账号拥有下列数据库对
  象:USER_DB.ENDUSER1.STUDENT和OTHER_DB.ENDUSER1.STUDENT。这里所加的限制是数据库用户名而不是SQL
   Server登录名,因为两者不一定要一样。
  同时,这些数据库的其他用户可以有同样名字的对象:
  
  USER_DB.DBO.STUDENT
  USER_DB.DEPT_ADMIN.STUDENT
  USER_DB.STUDENT_ADMIN.STUDENT
  OTHER_DB.DBO.STUDENT
   
  
  因此,建议你在引用数据库对象时包含所有者的名字。如果应用程序有多个数据库,建议你再把数据库名字
  也包含在引用中。如果查询跨越多个服务器,还要包括服务器名。
  
  SQL Server的每个连接都有一个当前数据库上下文,这是在登录时用USE语句设置的。例如,假设有下面的场
  景:
  
  一个用户,使用ENDUSER1账号,登录到USER_DB数据库上。用户请求STUDENT表。SQL Server就查询ENDUSER1.
  STUDENT表。如果找到,SQL Server就在USER_DB.ENDUSER1.STUDENT表上做要求的数据库操作。如果在
  ENDUSER1数据库账号下没有找到该表,SQL Server就为该数据库以dbo账号搜寻USER_DB.DBO.STUDENT。如果
  还是找不到该表,SQL Server就返回一个错误消息,指出该表不存在。
  如果另一个用户,例如DEPT_ADMIN拥有该表,则该表必须以数据库用户名作为前缀(DEPT_ADMIN.STUDENT)。
  另外,数据库名字缺省为在当前上下文中的数据库名字。
  如果被引用的表在另一个数据库中,则数据库名必须作为引用的一部分。例如,要访问在OTHERDB数据库中由
  ENDUSER1拥有的表STUDENT,就需要用OTHER_DB.ENDUSER1.STUDENT来引用。
  可以在数据库和表名之间加两个点号来省略对象的所有者名。例如,如果应用程序引用STUDENT_DB..STUDENT
  ,SQL Server就做如下搜

查看本文来源


  索引
  
  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 该表也典型的存在于用户会话或者创建它的过程的生命期内。但该表可以被多个用户共享。
  在最后一个引用它的

查看本文来源


  引用完整性

下表提供了一个用来定义referential完整性约束的语法比较。

约束 Oracle Microsoft SQL Server

PRIMARY KEY [CONSTRAINT constraint_name]

PRIMARY KEY (col_name [, col_name2 [..., col_name16]])

[USING INDEX storage_parameters] [CONSTRAINT constraint_name]

PRIMARY KEY [CLUSTERED | NONCLUSTERED] (col_name [, col_name2 [..., col_name16]])

[ON segment_name]

[NOT FOR REPLICATION]

UNIQUE [CONSTRAINT constraint_name]

UNIQUE (col_name [, col_name2 [..., col_name16]])

[USING INDEX storage_parameters] [CONSTRAINT constraint_name]

UNIQUE [CLUSTERED | NONCLUSTERED](col_name [, col_name2 [..., col_name16]])

[ON segment_name]

[NOT FOR REPLICATION]

FOREIGN KEY [CONSTRAINT constraint_name]

[FOREIGN KEY (col_name [, col_name2 [..., col_name16]])]

REFERENCES [owner.]ref_table [(ref_col [, ref_col2 [..., ref_col16]])]

[ON DELETE CASCADE] [CONSTRAINT constraint_name]

[FOREIGN KEY (col_name [, col_name2 [..., col_name16]])]

REFERENCES [owner.]ref_table [(ref_col [, ref_col2 [..., ref_col16]])]

[NOT FOR REPLICATION]

DEFAULT Column property, not a constraint

DEFAULT (constant_expression) [CONSTRAINT constraint_name]

DEFAULT {constant_expression | niladic-function | NULL}

[FOR col_name]

[NOT FOR REPLICATION]

CHECK [CONSTRAINT constraint_name]

CHECK (expression) [CONSTRAINT constraint_name]

CHECK [NOT FOR REPLICATION] (expression)

 

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

    [(argument [IN | OUT] datatype

    [, argument [IN | OUT] datatype]

{IS | AS} block CREATE PROC[EDURE] procedure_name        [;number]

    [

       {@parameter data_type} [VARYING]        [= default] [OUTPUT]

    ]

    [,…n]

[WITH

    { RECOMPILE   | ENCRYPTION |

      RECOMPILE, ENCRYPTION} ]

[FOR REPLICATION]

AS

    sql_statement […n]

 

在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;

   CURSOR C1 RETURN    STUDENT%ROWTYPE;

   FUNCTION    SHOW_RELUCTANT_STUDENTS

(WORKVAR OUT VARCHAR2)       RETURN NUMBER;

END P1;

/

CREATE OR REPLACE PACKAGE BODY    STUDENT_ADMIN.P1 AS CURSOR C1    RETURN STUDENT%ROWTYPE

IS

      SELECT * FROM       STUDENT_ADMIN.STUDENT

        WHERE NOT EXISTS

      (SELECT 'X' FROM       STUDENT_ADMIN.GRADE

      WHERE       GRADE.SSN=STUDENT.SSN) ORDER       BY SSN;

FUNCTION SHOW_RELUCTANT_STUDENTS

   (WORKVAR OUT VARCHAR2) RETURN    NUMBER IS

   WORKREC STUDENT%ROWTYPE;

   BEGIN

      IF NOT C1%ISOPEN THEN OPEN C1;

      ROWCOUNT :=0;

      ENDIF;

      FETCH C1 INTO WORKREC;

      IF (C1%NOTFOUND) THEN

        CLOSE C1;

        ROWCOUNT :=0;

      ELSE

        WORKVAR := WORKREC.FNAME||'         '||WORKREC.LNAME||

        ', social security number         '||WORKREC.SSN||' is not enrolled

           in any classes!';

        ROWCOUNT := ROWCOUNT + 1;

      ENDIF;

RETURN(ROWCOUNT); CREATE PROCEDURE

STUDENT_ADMIN.SHOW_

RELUCTANT_STUDENTS

AS SELECT FNAME+'' +LNAME+', social   security number'+ SSN+' is not enrolled in any  

 classes!'

FROM STUDENT_ADMIN.STUDENT S

WHERE NOT EXISTS

   (SELECT 'X' FROM    STUDENT_ADMIN.GRADE G

   WHERE G.SSN=S.SSN)

ORDER BY SSN

RETURN@@ROWCOUNT

GO

      EXCEPTION

WHEN OTHERS THEN

IF C1%ISOPEN THEN CLOSE C1;

ROWCOUNT :=0;

ENDIF;

RAISE_APPLICATION_ERROR(-20001,SQLERRM);

END SHOW_RELUCTANT_STUDENTS;

END P1;

/  

 

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

DEFAULT ; {@parameter data_type} [VARYING]

   [= default] [OUTPUT]

 

触发器(Triggers)

Oracle和Microsoft SQL Server都有触发器,但它们在执行上有些不同。

查看本文来源