Oracle 数据库向 MS SQL Server 7.0 的迁移(3)
当一个进程锁定另一个进程需要的页或表,而后者又锁定了前者所需要的页时,死锁就发
生了。死锁也称为“僵局”。SQL Server 自动检测并处理死锁。如果发现了死锁,服务器就
会终止处于“僵局”的用户进程。
每次数据修改后,程序代码都应检测消息编号 1205,它用于指示死锁。如果返回了这个
消息编号,则发生了死锁,并且事务被回滚。在这种情况下,应用程序必须重新启动事务。
使用一些简单的技巧,就可以避免死锁:
应用程序的各个部分均使用相同的顺序访问表。
在每个表上使用聚集索引,来实施显式行排序。
使事务保持简短。
有关详细信息,请参见 Microsoft Knowledge Base 文章:Detecting and Avoiding
Deadlocks in Microsoft SQL Server(Microsoft SQL Server 死锁的检测和避免)。
在 Oracle 中,要执行远程事务,必须能够使用数据库链接,来访问远程数据库节点。在
SQL Server 中,则必须能够访问一个“远程服务器”。远程服务器是在网络上运行 SQL
Server 的一个服务器,用户可使用本地服务器对它进行访问。当一个服务器被设置为远程服
务器时,用户无须显式登录,就可以使用其上的系统过程和存储过程。
远程服务器是成对设置的。必须对两个服务器进行配置,使之均将对方作为远程服务器。
必须使用 sp_addlinkedserver 系统存储过程或 SQL Server Enterprise Manager,把每个服
设置远程服务器之后,使用 sp_addremotelogin 系统存储过程或 SQL Server
Enterprise Manager,为必须访问远程服务器的用户设定远程登录 ID。这一步完成之后,必
然后,使用 EXECUTE 语句,运行远程服务器上的过程。以下示例执行了远程服务器
STUDSVR1 上的 validate_student 存储过程,并把指示成功或失败的返回状态存储在
DECLARE @retvalue1 int
EXECUTE @retvalue = STUDSVR1.student_db.student_admin.validate_student
有关详细信息,请参见 SQL Server Books Online。
如果在两个或多个网络数据库节点上对表进行更改,Oracle 就会自动启动一个分布式事
务。SQL Server 分布式事务则使用包含在 SQL Server 中的 Microsoft 分布式事务处理协
默认情况下,必须指示 SQL Server 参与分布式事务。可以使用以下方法之一,使 SQL
使用 BEGIN DISTRIBUTED TRANSACTION 语句。这个语句开始一个新的 MS DTC 事务。
使用直接调用 DTC 事务接口的客户应用程序。
在此例中,请注意对本地表 GRADE 和远程表 CLASS(使用 class_name 过程)的分布式
BEGIN DISTRIBUTED TRANSACTION
UPDATE STUDENT_ADMIN.GRADE
SET GRADE = 'B+' WHERE SSN = '111111111' AND CCODE = '1234'
DECLARE @retvalue1 int
EXECUTE @retvalue1 = CLASS_SVR1.dept_db.dept_admin.class_name '1234',
COMMIT TRANSACTION
GO
如果应用程序不能完成此事务,应用程序就会使用 ROLLBACK TRANSACTION 语句取消它。
如果应用程序失败或参与的资源管理器失败,MS DTC 就会取消此事务。MS DTC 不支持分布式
保存点或 SAVE TRANSACTION 语句。如果一个 MS DTC 事务终止或回滚,整个事务被回滚到分
布式事务的起始处,无论有多少个保存点都是如此。
Oracle 和 MS DTC 两阶段提交机制在操作上是类似的。在 SQL Server 两阶段提交的第
一阶段中,事务管理器请求每个参加的资源管理器为提交做准备。如果任何资源管理器不能准
如果所有资源管理器都可以成功地准备,则事务管理器广播提交决定。这是提交过程的第
二阶段。当资源管理器在准备时,它不知道事务将被提交还是被终止。MS DTC 有一个有序日
志,这样就可以永久保存提交或终止决定。如果资源管理器或事务管理器失败,它们重新连接
SQL 语言支持
这一部分概述了 Transact-SQL 和 PL/SQL 语言语法之间的相同点和不同点,并给出转换
要将 Oracle DML 语句和 PL/SQL 程序迁移到 SQL Server 时,请按下列步骤执行:
验证所有 SELECT、INSERT、UPDATE 和 DELETE 语句的语法是有效的。进行任何必要的修
把所有外部联接改为 SQL-92 标准外部联接语法。
用相应 SQL Server 函数替代 Oracle 函数。
检查所有的比较运算符。
用“+”字符串串联运算符代替“”字符串串联运算符。
用 Transact-SQL 程序代替 PL/SQL 程序。
把所有 PL/SQL 游标改为非游标 SELECT 语句或 Transact-SQL 游标。
用 Transact-SQL 过程代替 PL/SQL 过程、函数和包。
把 PL/SQL 触发器转换为 Transact-SQL 触发器。
使用 SET SHOWPLAN 语句,优化查询性能。
SELECT 语句
Oracle 和 Microsoft SQL Server 使用的 SELECT 语句语法类似。
SQL Server 不支持 Oracle 特定的基于开销的优化程序提示,它必须被删除。建议使用
的技术是,使用 SQL Server 基于开销的优化程序。有关详细信息,请参见本章后面的“SQL
SQL Server 不支持 Oracle 的 START WITHUCONNECT BY 子句。在 SQL Server 中,可以
SQL Server 不支持 Oracle 的 INTERSECT 和 MINUS 集合运算符。可使用 SQL Server
EXISTS 和 NOT EXISTS 子句,实现相同的结果。
在下面示例中,使用 INTERSECT 运算符,用于查找学生登记的所有课程的代码和名称。
注意,EXISTS 运算符是如何代替 INTERSECT 运算符的。返回的数据是相同的。
Transact-SQL values_list 参数提供了 SQL-92 标准关键字 DEFAULT,但 Oracle 不支
持。此关键字指定了,执行插入操作时使用列的默认值。如果指定列的默认值不存在,则插入
NULL。如果该列不允许 NULL,则返回一个错误消息。如果该列数据类型定义为 timestamp,
标识符列不能使用 DEFAULT 关键字。要生成下一个序列号,拥有 IDENTITY 属性的列不
能列在 column_list 或 values_clause 中。不需使用 DEFAULT 关键字,来获取列的默认值
。正如在 Oracle 中,如果列没有在 column_list 中引用,并且它有默认值,则默认值存放
一个有用的 Transact_SQL 选项 (EXECute procedure_name) 是,执行一个过程并将其结
果用管道输出到目标表或视图中。Oracle 不允许这样做。
UPDATE 语句
因为 Transact SQL 支持 Oracle UPDATE 命令使用的绝大多数语法,所以只需要极少的
修改。
在 SQL Server 中,此语句只能由表的所有者执行。在 Oracle 中,如果是表的所有者或
Oracle TRUNCATE TABLE 命令可以有选择地释放表中行所占用的存储空间。SQL Server
TRUNCATE TABLE 语句总是收回表数据及其相关索引所占用的空间。
标识符列和时间戳列中数据的处理
Oracle 序列是与任何给定的表或列均不直接相关的数据库对象。列和序列之间的关系是
在应用程序中实现的,即通过编程的方法将序列值赋给列。因此,Oracle 使用序列时,并不
实施任何规则。但是,在 Microsoft SQL Server 标识符列中,值不能被更新,并且不能使用
默认情况下,数据不能直接插入到标识符列。标识符列自动给表中插入的每个新行生成一
个唯一的序列号。可以使用下列 SET 语句改写这种默认设置:
SET IDENTITY_INSERT table_name ON
将 IDENTUTY_INSERT 设为 ON,用户就可以向新行的标识符列插入任何值。要防止出现
有重复号码的条目,必须为该列创建唯一索引。这条语句的目的是,允许用户给无意中删除的
行重新创建一个值。@@IDENTITY 函数可用来获取上一个标识值。
TRUNCATE TABLE 语句将标识符列重置为其起始 SEED 值。如果不想重置列的标识值,则
不使用 TRUNCATE TABLE 语句,而使用不带 WHERE 子句的 DELETE 语句。必须评估它对
Oracle 迁移造成的影响,因为 ORACLE SEQUENCE 在 TRUNCATE TABLE 命令之后不被重置。
处理 timestamp 列时,只能执行插入和删除。如果要更新一个 timestamp 列,会收到
Msg 272, Level 16, State 1 Can't update a TIMESTAMP column.
锁定请求的行
Oracle 使用 FOR UPDATE 子句来锁定 SELECT 命令中指定的行。不需要在 Microsoft
SQL Server 中使用对等的子句,因为这是默认行为。
行合计和 COMPUTE 子句
SQL Server COMPUTE 子句用于生成行合计函数(SUM、AVG、MIN、MAX 和 COUNT),它
们在查询结果中作为附加行出现。它允许查看一组结果的详细和汇总信息行。可以计算子组的
Oracle SELECT 命令语法不支持 COMPUTE 子句。但是,SQL Server COMPUTE 子句与
Oracle SQL*Plus 查询工具中的 COMPUTE 命令作用相似。
联接子句
Microsoft SQL Server 7.0 允许在一个联接子句中最多可联接 256 个表,包括临时表
在 Oracle 中使用外部联接时,外部联接运算符 (+) 通常放在该联接的子列(外键)旁
边。(+) 标识了具有较少唯一值的列。情况一般是这样,除非外键允许空值,在这种情况下,
(+) 被放在父(PRIMARY KEY 或 UNIQUE 约束)列上。(+) 不能放在等号 (=) 两边。
在 SQL Server 中,可以使用 *= 和 =* 外部联接运算符。* 用于标识有较多唯一值的列
。如果子(外键)列不允许空值,则 * 放在等号的父(PRIMARY KEY 或 UNIQUE 约束)列一
边。* 的位置和 Oracle 完全相反。* 不能放在等号 (=) 两边。
*= 和 =* 被认为是旧式联接运算符。SQL Server 也支持下面列出的 SQL-92 标准联接
运算符。建议使用这种语法。SQL-92 标准语法功能更强大,并且比 * 运算符的限制要少。
读取和修改 BLOB
Microsoft SQL Server 使用 text 和 image 列,来实现二进制大型对象 (BLOB)。
Oracle 使用 LONG 和 LONG RAW 列实现 BLOB。在 Oracle 中,SELECT 命令可以查询 LONG
在 SQL Server 中,可以使用标准的 Transact-SQL 语句或专门的 READTEXT 语句读取
text 和 image 列中的数据。READTEXT 语句允许读取 text 或 image 列的部分片段。
Oracle 没有提供处理 LONG 和 LONG RAW 的对等语句。
READTEXT 语句使用 text_pointer,它可以用 TEXTPTR 函数获得。TEXTPTR 函数返回一
个指针,它指向指定行中的 text 或 image 列,或如果返回不止一行,则它指向查询返回的
最后一行的 text 或 image 列。因为 TEXTPTR 函数返回一个 16 字节的二进制字符串,最好
声明一个局部变量来存放文本指针,然后由 READTEXT 使用该变量。
READTEXT 语句指定要返回的字节数。@@TEXTSIZE 函数中的值是要返回的字符或字节数
的限度,如果它小于 READTEXT 指定的大小,就会替代 READTEXT 语句指定值。
可使用带 TEXTSIZE 参数的 SET 语句,指定 SELECT 语句返回的文本数据的大小(字节
数)。如果指定 TEXTSIZE 为 0,其大小被重置为默认值 (4 KB)。设置 TEXTSIZE 参数,会
影响 @@TEXTSIZE 函数。当 SQL_MAX_LENGTH 语句选项更改时,SQL Server ODBC 驱动程序就
在 Oracle 中,UPDATE 和 INSERT 命令用于更改 LONG 和 LONG RAW 列中的值。在
SQL Server 中,可以使用标准的 UPDATE 和 INSERT 语句,也可以使用 UPDATETEXT 和
WRITETEXT 语句。UPDATETEXT 和 WRITETEXT 均允许无日志记录的选项,并且 UPDATETEXT 允
UPDATETEXT 语句可用于替换现有数据、删除现有数据或插入新数据。新插入的数据可以
WRITETEXT 语句可完全覆盖受其影响的列中的任何现有数据。使用 WRITETEXT 可替换文
本数据;使用 UPDATETEXT 可修改文本数据。UPDATETEXT 语句更加灵活,因为它只更改一部
有关详细信息,请参见 SQL Server Books Online。
本节中的表给出了 Oracle 和 SQL Server 标量值函数和合计函数之间的关系。尽管名称
看起来是相同的,但要注意,函数参数的数量和类型是不同的,这一点非常重要。此外,在这
个列表中,没有给出仅由 Microsoft SQL Server 提供的函数,因为本章仅限于讲述,如何方
便地实现从现有 Oracle 应用程序的迁移。Oracle 不支持函数的例子有:角度 (DEGREES)、
数字/数学函数
下面是 Oracle 支持的数字/数学函数及其 Microsoft SQL Server 对等函数。
字符函数
下面是 Oracle 支持的字符函数及其 Microsoft SQL Server 对等函数。
转换函数
下面是 Oracle 支持的转换函数及其 Microsoft SQL Server 对等函数。
条件测试
Oracle DECODE 语句和 Microsoft SQL Server CASE 表达式都执行条件测试。当
test_value 中的值符合下列任何表达式时,就会返回相关的值。如果不符合,则返回
default_value。如果没有指定 default_value,且不符合任何表达式,则 DECODE 和 CASE
返回 NULL。下表给出了语法以及一个转换的 DECODE 命令的示例。
CASE 表达式可以支持使用 SELECT 语句进行布尔测试,这是 DECODE 命令所不允许的。
有关 CASE 表达式的详细信息,请参见 SQL Server Books Online。
将值转换为不同的数据类型
Microsoft SQL Server CONVERT 和 CAST 函数均是多用途的转换函数。它们提供了相似
的功能,把一种数据类型的表达式转换为另一种数据类型,并支持多种特殊的数据格式:
CAST(expression AS data_type)
CONVERT (data type[(length)], expression [, style])
CAST 是一个 SQL-92 标准函数。这些函数执行与 Oracle TO_CHAR、TO_NUMBER、
TO_DATE、HEXTORAW 和 RAWTOHEX 函数相同的操作。
数据类型是指该表达式要转换成为的任何系统数据类型。不能使用用户定义的数据类型。
length 参数是可选的,它与 char、varchar、binary 和 varbinary 数据类型一起使用。可
允许的最大长度是 8000。
注意,字符串是如何转换成日期的。在 Oracle 中,默认的日期格式模型为“DD-MON-YY
”。如果使用任何其它格式,必须提供相应的日期格式模型。CONVERT 函数自动转换标准日期
当把日期转换成字符串时,CONVERT 函数默认输出为“dd mon yyyy hh:mm:ss:mmm(24h)
”。一种数字类型的编码用于设定到其它日期格式模型输出的格式。有关 CONVERT 函数的详
下表给出了 Microsoft SQL Server 日期的默认输出。
用户定义的函数
Oracle PL/SQL 函数可用于 Oracle SQL 语句中。在 Microsoft SQL Server 中,这一功
在下面的示例中,Oracle 用户定义的函数 GET_SUM_MAJOR 用于获取按专业 (major) 交
纳的学费总和。在 SQL Server 中,可通过把查询作为表使用,以替代这一函数。
模式匹配
SQL Server LIKE 关键字提供了一些 Oracle 不支持的、有用的通配符搜索选项。除了支
持两个 RDBMS 通用的 % 和 _ 通配符外,SQL Server 还支持 [] 和 [^] 字符。
[] 字符用于在给定范围内搜索某一单个字符。例如,如果在单字符位置搜索从 a 到 f
的字符,可以用 LIKE '[a-f]' 或 LIKE '[abcdef]' 指定。此表给出了这些附加通配符的用
法。
[^] 通配符集合用于指定不在给定范围内的字符。例如,如果接受除 a 到 f 以外的任何
字符,则使用 LIKE '[^a - f]' 或 LIKE '[^abcdef]'。
有关 LIKE 关键字的详细信息,请参见 SQL Server Books Online。
NULL 用法对比
尽管 Microsoft SQL Server 传统上支持 SQL-92 标准以及其它一些非标准的 NULL 行为
,但是它也支持 Oracle 中 NULL 的用法。
要执行分布式查询,SET ANSI_NULLS 应该设为 ON。
SQL Server ODBC 驱动程序和 SQL Server 的 OLE DB提供程序连接时,就会自动把
SET ANSI_NULLS 设为 ON。此设置可以在 ODBC 数据源、ODBC 连接属性设定,或者连接 SQL
Server 前,在应用程序中设置的 OLE DB 连接属性中设定。对来自 DB-Library 应用程序的
当 SET ANSI_DEFAILTS 为 ON 时,就会启用 SET ANSI_NULLS。
有关使用 NULL 的详细信息,请参见 SQL Server Books Online。
字符串串联
Oracle 将两个管道符号 () 作为字符串串联运算符,而 SQL Server 则使用加号 (+)
。这种差别只需要对应用程序代码进行小小的修改即可。
控制流语言控制 SQL 语句、语句块和存储过程的执行数据流。PL/SQL 和 Transact
关键字
以下是每种 RDBMS 支持的关键字。