[转]Orcle转SQL

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 语句语法类似。

Oracle
Microsoft SQL Server

SELECT [/*+ optimizer_hints*/]
[ALL | DISTINCT] select_list
[FROM
{table_name | view_name | select_statement}]
[WHERE clause]
[GROUP BY group_by_expression]
[HAVING search_condition]
[START WITH U CONNECT BY]
[{UNION | UNION ALL | INTERSECT |
MINUS} SELECT U]
[ORDER BY clause]
[FOR UPDATE]
SELECT select_list
[INTO new_table_]
FROM table_source
[WHERE search_condition]
[ GROUP BY [ALL] group_by_expression [,Un]
[ WITH { CUBE | ROLLUP } ]
[HAVING search_condition]
[ORDER BY order_expression [ASC | DESC] ]
In addition:
UNION Operator
COMPUTE Clause
FOR BROWSE Clause
OPTION Clause


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 运算符的。返回的数据是相同的。

Oracle
Microsoft SQL Server

SELECT CCODE, CNAME
FROM DEPT_ADMIN.CLASS
INTERSECT
SELECT C.CCODE, C.CNAME
FROM STUDENT_ADMIN.GRADE G,
DEPT_ADMIN.CLASS C
WHERE C.CCODE = G.CCODE
SELECT CCODE, CNAME
FROM DEPT_ADMIN.CLASS C
WHERE EXISTS
(SELECT 'X' FROM STUDENT_ADMIN.GRADE G
WHERE C.CCODE = G.CCODE)


在此例中,使用 MINUS 运算符,查找那些没有任何学生登记的课程。

Oracle
Microsoft SQL Server

SELECT CCODE, CNAME
FROM DEPT_ADMIN.CLASS
MINUS
SELECT C.CCODE, C.CNAME
FROM STUDENT_ADMIN.GRADE G,
DEPT_ADMIN.CLASS C
WHERE C.CCODE = G.CCODE
SELECT CCODE, CNAME
FROM DEPT_ADMIN.CLASSC
WHERE NOT EXISTS
(SELECT 'X' FROM STUDENT_ADMIN.GRADE G
WHERE C.CCODE = G.CCODE)


INSERT 语句

Oracle 和 Microsoft SQL Server 使用的 INSERT 语句语法类似。

Oracle
Microsoft SQL Server

INSERT INTO
{table_name | view_name | select_statement} [(column_list)]
{values_list | select_statement}
INSERT [INTO]
{
table_name [ [AS] table_alias] WITH ( [Un])
| view_name [ [AS] table_alias]
| rowset_function_limited
}

{ [(column_list)]
{ VALUES ( { DEFAULT
| NULL
| expression
}[,Un]
)
| derived_table
| execute_statement
}
}
| DEFAULT VALUES


Transact-SQL 语言支持对表和视图的插入,但不支持对 SELECT 语句的 INSERT 操作。如果 Oracle 应用程序代码执行对 SELECT 语句的插入操作,则必须对它进行修改。

Oracle
Microsoft SQL Server

INSERT INTO (SELECT SSN, CCODE, GRADE FROM GRADE)
VALUES ('111111111', '1111',NULL)
INSERT INTO GRADE (SSN, CCODE, GRADE)
VALUES ('111111111', '1111',NULL)


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 命令使用的绝大多数语法,所以只需要极少的修改。

Oracle
Microsoft SQL Server

UPDATE
{table_name | view_name | select_statement}
SET [column_name(s) = {constant_value | expression | select_statement | column_list |
variable_list]
{where_statement}
UPDATE
{
table_name [ [AS] table_alias] WITH ( [Un])
view_name [ [AS] table_alias]
| rowset_function_limited
}
SET
{column_name = {expression | DEFAULT | NULL}
| @variable = expression
| @variable = column = expression } [,Un]

{{[FROM { } [,Un] ]

[WHERE
] }
|
[WHERE CURRENT OF
{ { [GLOBAL] cursor_name } | cursor_variable_name}
] }
[OPTION ( [,Un] )]


Transact-SQL UPDATE 语句不支持对 SELECT 语句的更新操作。如果 Oracle 应用程序代码对 SELECT 语句进行更新,则可以把 SELECT 语句转换成一个视图,然后在 SQL Server UPDATE 语句中使用该视图名称。请参见前面“INSERT 语句”中的示例。

Oracle UPDATE 命令只能使用一个 PL/SQL 块中的程序变量。要使用变量,Transact-SQL 语言并不需要使用块。

Oracle
Microsoft SQL Server

DECLARE
VAR1 NUMBER(10,2);
BEGIN
VAR1 := 2500;
UPDATE STUDENT_ADMIN.STUDENT
SET TUITION_TOTAL = VAR1;
END;
DECLARE
@VAR1 NUMERIC(10,2)
SELECT @VAR1 = 2500
UPDATE STUDENT_ADMIN.STUDENT
SET TUITION_TOTAL=@VAR1


在 SQL Server 中,DEFAULT 关键字可用于将一列设为其默认值。但不能使用 Oracle UPDATE 命令,将一列设为默认值。

Transact-SQL 和 Oracle SQL 均支持在 UPDATE 语句中使用子查询。但是,Transact-SQL FROM 子句可用来创建一个基于联接的 UPDATE。这一功能使 UPDATE 语法可读性更好,在某些情况下还能改善性能。

Oracle
Microsoft SQL Server

UPDATE
STUDENT_ADMIN.STUDENT S
SET TUITION_TOTAL = 1500
WHERE SSN IN (SELECT SSN
FROM GRADE G
WHERE G.SSN = S.SSN
AND G.CCODE = '1234')
Subquery:
UPDATE
STUDENT_ADMIN.STUDENT S
SET TUITION_TOTAL = 1500
WHERE SSN IN (SELECT SSN
FROM GRADE G
WHERE G.SSN = S.SSN
AND G.CCODE = '1234')
FROM clause:
UPDATE
STUDENT_ADMIN.STUDENT S
SET TUITION_TOTAL = 1500
FROM GRADE G
WHERE S.SSN = G.SSN
AND G.CCODE = '1234'


DELETE 语句

在大多数情况下,不需要修改 DELETE 语句。如果要对 Oracle 中的 SELECT 语句执行删除操作,则必须修改 SQL Server 语法,因为 Transact-SQL 不支持这一功能。

Transact-SQL 支持在 WHERE 子句中使用子查询,以及在 FROM 子句中使用联接。后者可产生更有效的语句。请参见前面“UPDATE 语句”中的示例。

Oracle
Microsoft SQL Server

DELETE [FROM]
{table_name | view_name | select_statement}
[WHERE clause]
DELETE
[FROM ]
{
table_name [ [AS] table_alias] WITH ( [Un])
| view_name [ [AS] table_alias]
| rowset_function_limited
}

[ FROM { } [,Un] ]
[WHERE
{
| { [ CURRENT OF
{
{ [ GLOBAL ] cursor_name }
cursor_variable_name
}
]
}
]
[OPTION ( [,Un])]


TRUNCATE TABLE 语句

Oracle 和 Microsoft SQL Server 使用的 TRUNCATE TABLE 语句语法类似。TRUNCATE TABLE 用于从表中删除所有的行,并且不能回滚。表结构及其所有索引继续存在。DELETE 触发器不执行。如果表被一个 FOREIGN KEY 约束引用,则它不能被截断。

Oracle
Microsoft SQL Server

TRUNCATE TABLE table_name
[{DROP | REUSE} STORAGE]
TRUNCATE TABLE table_name


在 SQL Server 中,此语句只能由表的所有者执行。在 Oracle 中,如果是表的所有者或拥有 DELETE TABLE 系统权限,就可以执行此命令。

Oracle TRUNCATE TABLE 命令可以有选择地释放表中行所占用的存储空间。SQL Server TRUNCATE TABLE 语句总是收回表数据及其相关索引所占用的空间。

标识符列和时间戳列中数据的处理

Oracle 序列是与任何给定的表或列均不直接相关的数据库对象。列和序列之间的关系是在应用程序中实现的,即通过编程的方法将序列值赋给列。因此,Oracle 使用序列时,并不实施任何规则。但是,在 Microsoft SQL Server 标识符列中,值不能被更新,并且不能使用 DEFAULT 关键字。

默认情况下,数据不能直接插入到标识符列。标识符列自动给表中插入的每个新行生成一个唯一的序列号。可以使用下列 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 中,则没有联接限制。

在 Oracle 中使用外部联接时,外部联接运算符 (+) 通常放在该联接的子列(外键)旁边。(+) 标识了具有较少唯一值的列。情况一般是这样,除非外键允许空值,在这种情况下,(+) 被放在父(PRIMARY KEY 或 UNIQUE 约束)列上。(+) 不能放在等号 (=) 两边。

在 SQL Server 中,可以使用 *= 和 =* 外部联接运算符。* 用于标识有较多唯一值的列。如果子(外键)列不允许空值,则 * 放在等号的父(PRIMARY KEY 或 UNIQUE 约束)列一边。* 的位置和 Oracle 完全相反。* 不能放在等号 (=) 两边。

*= 和 =* 被认为是旧式联接运算符。SQL Server 也支持下面列出的 SQL-92 标准联接运算符。建议使用这种语法。SQL-92 标准语法功能更强大,并且比 * 运算符的限制要少。

联接操作
说明

CROSS JOIN
这是两个表的交叉乘积。它与旧式联接中未指定 WHERE 子句而返回的行相同。在 Oracle 中,这种类型联接称为笛卡尔联接。

INNER
这种联接指定,所有内部行均要返回。丢弃任何不匹配的行。这和标准的 Oracle 表联接相同。

LEFT[OUTER]
这种类型的联接指定,所有左表的外部行均要返回,即使没找到匹配的列,也就如此。这和 Oracle 外部联接 (+) 的操作类似。

RIGHT[OUTER]
这种类型的联接指定,所有右表的外部行均要返回,即使没找到匹配的列,也是如此。这和 Oracle 外部联接 (+) 的操作类似。

FULL [OUTER]
如果两个表中的一行不符合选择标准,则指定将这一行加到结果集中,并且将其对应于另一表的输出列设为 NULL。这和将 Oracle 外部联接运算符放在“=”号两边 (col1(+)=col2(+)) 的效果是一样的,但后者在 Oracle 中是不允许的。


下面的代码示例返回所有学生登记的课程列表。外部联接定义在学生 (student) 和成绩 (grade) 表之间,成绩表允许所有的学生出现在上面,甚至那些没有登记任何课程的学生也是如此。外部联接也加到课程表上,以返回课程名称。如果外部联接不加到课程表上,就不会返回那些没有登记任何课程的学生,因为他们的课程代码 (CCODE) 为空。

Oracle
Microsoft SQL Server

SELECT S.SSN AS SSN,
FNAME, LNAME
FROM STUDENT_ADMIN.STUDENT S,
DEPT_ADMIN.CLASS C,
STUDENT_ADMIN.GRADE G
WHERE S.SSN = G.SSN(+)
AND G.CCODE = C.CCODE(+)
SELECT S.SSN AS SSN,
FNAME, LNAME
FROM STUDENT_ADMIN.GRADE G
RIGHT OUTER JOIN
STUDENT_ADMIN.STUDENT S
ON G.SSN = S.SSN
LEFT OUTER JOIN
DEPT_ADMIN.CLASS C
ON G.CCODE = C.CCODE


将 SELECT 语句做为表名使用

Microsoft SQL Server 和 Oracle 均支持在执行查询时,把 SELECT 语句作为表的来源使用。SQL Server 需要一个别名;对 Oracle,别名的使用是可选的。

Oracle
Microsoft SQL Server

SELECT SSN, LNAME, FNAME,
TUITION_PAID, SUM_PAID
FROM STUDENT_ADMIN.STUDENT,
(SELECT SUM(TUITION_PAID) SUM_PAID FROM STUDENT_ADMIN.STUDENT)
SELECT SSN, LNAME, FNAME,
TUITION_PAID, SUM_PAID
FROM STUDENT_ADMIN.STUDENT,
(SELECT SUM(TUITION_PAID) SUM_PAID FROM STUDENT_ADMIN.STUDENT) SUM_STUDENT


读取和修改 BLOB

Microsoft SQL Server 使用 text 和 image 列,来实现二进制大型对象 (BLOB)。Oracle 使用 LONG 和 LONG RAW 列实现 BLOB。在 Oracle 中,SELECT 命令可以查询 LONG 和 LONG RAW 列中的值。

在 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 驱动程序就会自动设置 TEXTSIZE 参数。

在 Oracle 中,UPDATE 和 INSERT 命令用于更改 LONG 和 LONG RAW 列中的值。在 SQL Server 中,可以使用标准的 UPDATE 和 INSERT 语句,也可以使用 UPDATETEXT 和 WRITETEXT 语句。UPDATETEXT 和 WRITETEXT 均允许无日志记录的选项,并且 UPDATETEXT 允许对 text 或 image 列进行部分更新。

UPDATETEXT 语句可用于替换现有数据、删除现有数据或插入新数据。新插入的数据可以是常量、表名、列名或文本指针。

WRITETEXT 语句可完全覆盖受其影响的列中的任何现有数据。使用 WRITETEXT 可替换文本数据;使用 UPDATETEXT 可修改文本数据。UPDATETEXT 语句更加灵活,因为它只更改一部分文本或图像值,而不是更改全部。

有关详细信息,请参见 SQL Server Books Online。

本节中的表给出了 Oracle 和 SQL Server 标量值函数和合计函数之间的关系。尽管名称看起来是相同的,但要注意,函数参数的数量和类型是不同的,这一点非常重要。此外,在这个列表中,没有给出仅由 Microsoft SQL Server 提供的函数,因为本章仅限于讲述,如何方便地实现从现有 Oracle 应用程序的迁移。Oracle 不支持函数的例子有:角度 (DEGREES)、圆周率 (PI) 和随机数 (RAND)。

数字/数学函数

下面是 Oracle 支持的数字/数学函数及其 Microsoft SQL Server 对等函数。

函数
Oracle
Microsoft SQL Server

绝对值
ABS
ABS

反余弦
ACOS
ACOS

反正弦
ASIN
ASIN

n 的反正切
ATAN
ATAN

m/n 的反正切
ATAN2
ATN2

>=值的最小整数
CEIL
CEILING

余弦
COS
COS

双曲余弦
COSH
COT

指数值
EXP
EXP

<=值的最大整数
FLOOR
FLOOR

自然对数
LN
LOG

以任何为底的对数
LOG(N)
暂缺

以 10 为底的对数
LOG(10)
LOG10

模数(余数)
MOD
USE MODULO (%) OPERATOR


POWER
POWER

随机数
暂缺
RAND

舍入
ROUND
ROUND

数的符号
SIGN
SIGN

正弦
SIN
SIN

双曲正弦
SINH
暂缺

平方根
SQRT
SQRT

正切
TAN
TAN

双曲正切
TANH
暂缺

截尾
TRUNC
暂缺

列表中的最大数
GREATEST
暂缺

列表中的最小数
LEAST
暂缺

如果为 NULL,转换成数字
NVL
ISNULL


字符函数

下面是 Oracle 支持的字符函数及其 Microsoft SQL Server 对等函数。

函数
Oracle
Microsoft SQL Server

把字符转换成 ASCII
ASCII
ASCII

字符串串联
CONCAT
(表达式 + 表达式)

把 ASCII 转换成字符
CHR
CHAR

返回字符串中的起始字符(从左)
INSTR
CHARINDEX

将字符转换成小写
LOWER
LOWER

将字符转换成大写
UPPER
UPPER

在字符串的左边填充字符
LPAD
暂缺

删除前导空格
LTRIM
LTRIM

删除尾空格
RTRIM
RTRIM

字符串中模式的起始点
INSTR
PATINDEX

多次重复字符串
RPAD
REPLICATE

字符串的语音表示
SOUNDEX
SOUNDEX

重复空格的字符串
RPAD
SPACE

从数字数据转换而来的字符数据
TO_CHAR
STR

子串
SUBSTR
SUBSTRING

字符替换
REPLACE
STUFF

字符串中每个词的第一个字母大写
INITCAP
暂缺

字符串转换
TRANSLATE
暂缺

字符串长度
LENGTH
DATELENGTH 或 LEN

列表中的最大字符串
GREATEST
暂缺

列表中的最小字符串
LEAST
暂缺

如果为 NULL,则转换字符串
NVL
ISNULL


日期函数

下面是 Oracle 支持的日期函数及其 Microsoft SQL Server 对等函数。

函数
Oracle
Microsoft SQL Server

日期加
(日期列 +/- 值)或 ADD_MONTHS
DATEADD

日期间的间隔
(日期列 +/- 值)或 MONTHS_BETWEEN
DATEDIFF

当前日期和时间
SYSDATE
GETDATE()

月的最后一天
LAST_DAY
暂缺

时区转换
NEW_TIME
暂缺

该日期后的第一个工作日
NEXT_DAY
暂缺

日期的字符串表示
TO_CHAR
DATENAME

日期的整数表示
TO_NUMBER (TO_CHAR))
DATEPART

日期舍入
ROUND
CONVERT

日期截尾
TRUNC
CONVERT

字符串转换为日期
TO_DATE
CONVERT

如果为 NULL,则转换日期
NVL
ISNULL


转换函数

下面是 Oracle 支持的转换函数及其 Microsoft SQL Server 对等函数。

函数
Oracle
Microsoft SQL Server

数字到字符
TO_CHAR
CONVERT

字符到数字
TO_NUMBER
CONVERT

日期到字符
TO_CHAR
CONVERT

字符到日期
TO_DATE
CONVERT

十六进制到二进制
HEX_TO_RAW
CONVERT

二进制到十六进制
RAW_TO_HEX
CONVERT


其它行级函数

下面是 Oracle 支持的其它行级函数及其 Microsoft SQL Server 对等函数。

函数
Oracle
Microsoft SQL Server

返回第一个非空表达式
DECODE
COALESCE

当前序列值
CURRVAL
暂缺

下一个序列值
NEXTVAL
暂缺

如果表达式 1 = 表达式 2,则返回空
DECODE
NULLIF

用户的登录 ID 号
UID
SUSER_ID

用户的登录名
USER
SUSER_NAME

用户的数据库 ID 号
UID
USER_ID

用户的数据库名
USER
USER_NAME

当前用户
CURRENT_USER
CURRENT_USER

用户环境(审核记录)
USERENV
暂缺

CONNECT BY 子句的级别
LEVEL
暂缺


合计函数

下面是 Oracle 支持的合计函数及其 Microsoft SQL Server 对等函数。

函数
Oracle
Microsoft SQL Server

平均值
AVG
AVG

计数
COUNT
COUNT

最大值
MAX
MAX

最小值
MIN
MIN

标准偏差
STDDEV
STDEV 或 STDEVP

汇总
SUM
SUM

方差
VARIANCE
VAR 或 VARP


条件测试

Oracle DECODE 语句和 Microsoft SQL Server CASE 表达式都执行条件测试。当 test_value 中的值符合下列任何表达式时,就会返回相关的值。如果不符合,则返回 default_value。如果没有指定 default_value,且不符合任何表达式,则 DECODE 和 CASE 返回 NULL。下表给出了语法以及一个转换的 DECODE 命令的示例。

Oracle
Microsoft SQL Server

DECODE (test_value,
expression1, value1
[[,expression2, value2] [U]]
[,default_value]
)

CREATE VIEW STUDENT_ADMIN.STUDENT_GPA
(SSN, GPA)
AS SELECT SSN, ROUND(AVG(DECODE(grade
,'A', 4
,'A+', 4.3
,'A-', 3.7
,'B', 3
,'B+', 3.3
,'B-', 2.7
,'C', 2
,'C+', 2.3
,'C-', 1.7
,'D', 1
,'D+', 1.3
,'D-', 0.7
,0)),2)
FROM STUDENT_ADMIN.GRADE
GROUP BY SSN
CASE input_expression
WHEN when_expression THEN result_expression
[[WHEN when_expression THEN result_expression] [...]]
[ELSE else_result_expression]
END

CREATE VIEW STUDENT_ADMIN.STUDENT_GPA
(SSN, GPA)
AS SELECT SSN, ROUND(AVG(CASE grade
WHEN 'A' THEN 4
WHEN 'A+' THEN 4.3
WHEN 'A-' THEN 3.7
WHEN 'B' THEN 3
WHEN 'B+' THEN 3.3
WHEN 'B-' THEN 2.7
WHEN 'C' THEN 2
WHEN 'C+' THEN 2.3
WHEN 'C-' THEN 1.7
WHEN 'D' THEN 1
WHEN 'D+' THEN 1.3
WHEN 'D-' THEN 0.7
ELSE 0
END),2)
FROM STUDENT_ADMIN.GRADE
GROUP BY SSN


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
Microsoft SQL Server

字符到数字
TO_NUMBER('10')
CONVERT(numeric, '10')

数字到字符
TO_CHAR(10)
CONVERT(char, 10)

字符到日期
TO_DATE('04-JUL-97')
TO_DATE('04-JUL-1997',
'dd-mon-yyyy')
TO_DATE('July 4, 1997',
'Month dd, yyyy')
CONVERT(datetime, '04-JUL-97')
CONVERT(datetime, '04-JUL-1997')
CONVERT(datetime, 'July 4, 1997')

日期到字符
TO_CHAR(sysdate)
TO_CHAR(sysdate, 'dd mon yyyy')
TO_CHAR(sysdate, 'mm/dd/yyyy')
CONVERT(char, GETDATE())
CONVERT(char, GETDATE(), 106)
CONVERT(char, GETDATE(), 101)

十六进制到二进制
HEXTORAW('1F')
CONVERT(binary, '1F')

二进制到十六进制
RAWTOHEX
(binary_column)
CONVERT(char, binary_column)


注意,字符串是如何转换成日期的。在 Oracle 中,默认的日期格式模型为“DD-MON-YY”。如果使用任何其它格式,必须提供相应的日期格式模型。CONVERT 函数自动转换标准日期格式,而无须格式模型。

当把日期转换成字符串时,CONVERT 函数默认输出为“dd mon yyyy hh:mm:ss:mmm(24h)”。一种数字类型的编码用于设定到其它日期格式模型输出的格式。有关 CONVERT 函数的详细信息,请参见 SQL Server Books Online。

下表给出了 Microsoft SQL Server 日期的默认输出。

不带世纪
带有世纪
标准
输出

-
0 或 100 (*)
默认
mon dd yyyy hh:miAM(或 PM)

1
101
美国
mm/dd/yy

2
102
ANSI
yy.mm.dd

3
103
英国/法国
dd/mm/yy

4
104
德国
dd.mm.yy

5
105
意大利
dd-mm-yy

6
106
-
dd mon yy

7
107
-
mon dd, yy

8
108
-
hh:mm:ss

-
9 或 109 (*)
默认毫秒
mon dd yyyy hh:mi:ss:mmm(AM 或 PM)

10
110
美国
mm-dd-yy

11
111
日本
yy/mm/dd

12
112
ISO
yymmdd

-
13 或 113 (*)
欧洲默认
dd mon yyyy hh:mm:ss:mmm(24h)

14
114
-
hh:mi:ss:mmm(24h)


用户定义的函数

Oracle PL/SQL 函数可用于 Oracle SQL 语句中。在 Microsoft SQL Server 中,这一功能通常以其它方式实现。

在下面的示例中,Oracle 用户定义的函数 GET_SUM_MAJOR 用于获取按专业 (major) 交纳的学费总和。在 SQL Server 中,可通过把查询作为表使用,以替代这一函数。

Oracle
Microsoft SQL Server

SELECT SSN, FNAME, LNAME, ) TUITION_PAID,
TUITION_PAID/GET_SUM_
MAJOR(MAJOR)
AS PERCENT_MAJOR
FROM STUDENT_ADMIN.STUDENT
SELECT SSN, FNAME, LNAME, TUITION_PAID, TUITION_PAID/SUM_MAJOR AS PERCENT_MAJOR
FROM STUDENT_ADMIN.STUDENT,
(SELECT MAJOR, SUM(TUITION_PAID) SUM_MAJOR
FROM STUDENT_ADMIN.STUDENT
GROUP BY MAJOR) SUM_STUDENT
WHERE STUDENT.MAJOR = SUM_STUDENT.MAJOR

CREATE OR REPLACE FUNCTION GET_SUM_MAJOR
(INMAJOR VARCHAR2) RETURN NUMBER
AS SUM_PAID NUMBER;
BEGIN
SELECT SUM(TUITION_PAID) INTO SUM_PAID
FROM STUDENT_ADMIN.STUDENT
WHERE MAJOR = INMAJOR;
RETURN(SUM_PAID);
END GET_SUM_MAJOR;
不需要 CREATE FUNCTION 语法;使用 CREATE PROCEDURE 语法。


Oracle 和 Microsoft SQL Server 比较运算符几乎是相同的。

运算符
Oracle
Microsoft SQL Server

等于
(=)
(=)

大于
(>)
(>)

小于
(<)
(<)

大于或等于
(>=)
(>=)

小于或等于
(<=)
(<=)

不等于
(!=, <>, ^=)
(!=, <>, ^=)

不大于,不小于
暂缺
!> , !<

在集合的任何成员中
IN
IN

不在集合的任何成员中
NOT IN
NOT IN

集合中的任一值
ANY, SOME
ANY, SOME

引用集合中的
所有值
!= ALL, <> ALL, < ALL,
> ALL, <= ALL, >= ALL, != SOME, <> SOME,
< SOME, > SOME,
<= SOME, >= SOME
!= ALL, <> ALL, < ALL,
> ALL, <= ALL, >= ALL, != SOME, <> SOME,
< SOME, > SOME,
<= SOME, >= SOME

与模式相似
LIKE
LIKE

与模式不相似
NOT LIKE
NOT LIKE

x 和 y 之间的值
BETWEEN x AND y
BETWEEN x AND y

不在两者之间的值_
NOT BETWEEN
NOT BETWEEN

值存在
EXISTS
EXISTS

值不存在
NOT EXISTS
NOT EXISTS

值{为|不为} NULL
IS NULL, IS NOT NULL
相同。也可以使用 = NULL、
!=NULL,用于向后兼容性(不推荐使用)。


模式匹配

SQL Server LIKE 关键字提供了一些 Oracle 不支持的、有用的通配符搜索选项。除了支持两个 RDBMS 通用的 % 和 _ 通配符外,SQL Server 还支持 [] 和 [^] 字符。

[] 字符用于在给定范围内搜索某一单个字符。例如,如果在单字符位置搜索从 a 到 f 的字符,可以用 LIKE '[a-f]' 或 LIKE '[abcdef]' 指定。此表给出了这些附加通配符的用法。

Oracle
Microsoft SQL Server

SELECT * FROM STUDENT_ADMIN.STUDENT
WHERE LNAME LIKE 'A%'
OR LNAME LIKE 'B%'
OR LNAME LIKE 'C%'
SELECT * FROM STUDENT_ADMIN.STUDENT
WHERE LNAME LIKE '[ABC]%'


[^] 通配符集合用于指定不在给定范围内的字符。例如,如果接受除 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_NULLS 默认为 OFF。

当 SET ANSI_DEFAILTS 为 ON 时,就会启用 SET ANSI_NULLS。

有关使用 NULL 的详细信息,请参见 SQL Server Books Online。

字符串串联

Oracle 将两个管道符号 (||) 作为字符串串联运算符,而 SQL Server 则使用加号 (+)。这种差别只需要对应用程序代码进行小小的修改即可。

Oracle
Microsoft SQL Server

SELECT FNAME||' '||LNAME AS NAME
FROM STUDENT_ADMIN.STUDENT
SELECT FNAME +' '+ LNAME AS NAME
FROM STUDENT_ADMIN.STUDENT


控制流语言控制 SQL 语句、语句块和存储过程的执行数据流。PL/SQL 和 Transact SQL 提供了许多相同的结构,但在语法上有一些差异。

关键字

以下是每种 RDBMS 支持的关键字。

语句
Oracle PL/SQL
Microsoft SQL Server
Transact-SQL

声明变量
DECLARE
DECLARE

语句块
BEGIN...END;
BEGIN...END

条件处理
IFUTHEN,
ELSIFUTHEN,
ELSE
ENDIF;
IFU[BEGINUEND]
ELSE
[BEGINUEND]
ELSE IF
CASE expression

无条件退出
RETURN
RETURN

无条件退出到当前程序块结束后紧接着的那条语句
EXIT
BREAK

重新开始一个 WHILE 循环
暂缺
CONTINUE

等待指定的间隔
暂缺 (dbms_lock.sleep)
WAITFOR

循环控制
WHILE LOOPUEND LOOP;

LABELUGOTO LABEL;
FORUEND LOOP;
LOOPUEND LOOP;
WHILE
BEGINU END

LABELUGOTO LABEL

程序注释
/* U */, --
/* U */, --

打印输出
RDBMS_OUTPUT.PUT_
LINE
PRINT

提出程序错误
RAISE_APPLICATION_
ERROR
RAISERROR

执行程序
EXECUTE
EXECUTE

语句终止符
分号 (;)
暂缺


声明变量

Transact-SQL 和 PL/SQL 变量是使用 DECLARE 关键字来创建的。Transact-SQL 变量用 @ 来标识,并且像 PL/SQL 变量一样,第一次创建时该变量被初始化为空值。

Oracle
Microsoft SQL Server

DECLARE
VSSN CHAR(9);
VFNAME VARCHAR2(12);
VLNAME VARCHAR2(20);
VBIRTH_DATE DATE;
VLOAN_AMOUNT NUMBER(12,2);
DECLARE
@VSSN CHAR(9),
@VFNAME VARCHAR2(12),
@VLNAME VARCHAR2(20),
@VBIRTH_DATE DATETIME,
@VLOAN_AMOUNT NUMERIC(12,2)


Transact-SQL 不支持 %TYPE 和 %ROWTYPE 变量数据类型定义。在 DECLARE 命令中,不能对 Transact-SQL 变量进行初始化。Oracle NOT NULL 和 CONSTANT 关键字不能用在 Microsoft SQL Server 数据类型定义中。

与 Oracle LONG 和 LONG RAW 数据类型一样,text 和 image 数据类型不能用于变量声明。此外,不支持 PL/SQL 类型的记录和表定义。

变量赋值

Oracle 和 Microsoft SQL Server 提供以下方法,给局部变量赋值。

Oracle
Microsoft SQL Server

赋值运算符 (:=)
SET @local_variable = value

用于从一行中选择列值的 SELECT...INTO 语法。
SELECT @local_variable = expression [FROMU] 用于为字面值、涉及其它局部变量的表达式或一行中的列值赋值。

FETCHUINTO 语法
FETCHUINTO 语法


以下是一些语法示例。

Oracle
Microsoft SQL Server

DECLARE VSSN CHAR(9);
VFNAME VARCHAR2(12);
VLNAME VARCHAR2(20);
BEGIN
VSSN := '123448887';
SELECT FNAME, LNAME INTO VFNAME, VLNAME FROM STUDENTS WHERE SSN=VSSN;
END;
DECLARE @VSSN CHAR(9),
@VFNAME VARCHAR(12),
@VLNAME VARCHAR(20)
SET @VSSN = '12355887'
SELECT @VFNAME=FNAME, @VLNAME=LNAME FROM STUDENTS WHERE SSN = @VSSN


语句块

Oracle PL/SQL 和 Microsoft SQL Server Transact-SQL 支持使用 BEGINUEND 术语,来指定程序块。Transact-SQL 不要求在 DECLARE 语句后面使用语句块。在 Microsoft SQL Server 中,如果 IF 语句和 WHILE 循环执行不止一个语句,需要使用 BEGINUEND 语句块。

Oracle
Microsoft SQL Server

DECLARE
DECLARE VARIABLES ...
BEGIN -- THIS IS REQUIRED SYNTAX
PROGRAM_STATEMENTS ...
IF ...THEN
STATEMENT1;
STATEMENT2;
STATEMENTN;
END IF;
WHILE ...LOOP
STATEMENT1;
STATEMENT2;
STATEMENTN;
END LOOP;
END; -- THIS IS REQUIRED SYNTAX
DECLARE
DECLARE VARIABLES ...
BEGIN -- THIS IS OPTIONAL SYNTAX
PROGRAM_STATEMENTS ...
IF ...
BEGIN
STATEMENT1
STATEMENT2
STATEMENTN
END
WHILE ...
BEGIN
STATEMENT1
STATEMENT2
STATEMENTN
END
END -- THIS IS REQUIRED SYNTAX


条件处理

Microsoft SQL Server Transact-SQL 条件语句包含 IF 和 ELSE 语句,而不是 Oracle PL/SQL 中的 ELSIF 语句。可以嵌套多个 IF 语句,来达到同样的效果。对于大量的条件测试,CASE 表达式更容易阅读。

Oracle
Microsoft SQL Server

DECLARE
VDEGREE_PROGRAM CHAR(1);
VDEGREE_PROGRAM_NAME VARCHAR2(20);
BEGIN
VDEGREE_PROGRAM := 'U';
IF VDEGREE_PROGRAM = 'U' THEN
VDEGREE_PROGRAM_NAME :=
'Undergraduate';
ELSIF VDEGREE_PROGRAM = 'M' THEN VDEGREE_PROGRAM_
NAME := 'Masters';
ELSIF VDEGREE_PROGRAM = 'P' THEN VDEGREE_PROGRAM_
NAME := 'PhD';
ELSE VDEGREE_PROGRAM_
NAME := 'Unknown';
END IF;
END;
DECLARE
@VDEGREE_PROGRAM CHAR(1),
@VDEGREE_PROGRAM_NAME VARCHAR(20)
SELECT @VDEGREE_PROGRAM = 'U'
SELECT @VDEGREE_PROGRAM_
NAME = CASE @VDEGREE_PROGRAM
WHEN 'U' THEN 'Undergraduate'
WHEN 'M' THEN 'Masters'
WHEN 'P' THEN 'PhD'.
ELSE 'Unknown'
END


重复的语句执行(循环)

Oracle PL/SQL 提供了无条件的 LOOP 和 FOR LOOP。而 Transact-SQL 则提供了 WHILE 循环和 GOTO 语句,来达到循环的目的。

WHILE Boolean_expression
{sql_statement | statement_block}
[BREAK] [CONTINUE]

对于一个或多个语句的重复执行,WHILE 循环测试一个布尔表达式。只要给定的表达式求值为 TRUE,语句就会重复执行。如果要执行多个语句,它们必须放在一个 BEGINUEND 块中。

Oracle
Microsoft SQL Server

DECLARE
COUNTER NUMBER;
BEGIN
COUNTER := 0
WHILE (COUNTER <5) LOOP
COUNTER := COUNTER + 1;
END LOOP;
END;
DECLARE
@COUNTER NUMERIC
SELECT@COUNTER = 1
WHILE (@COUNTER <5)
BEGIN
SELECT @COUNTER =
@COUNTER +1
END


可以使用 BREAK 和 CONTINUE 关键字,从循环的内部控制语句的执行。BREAK 关键字导致从 WHILE 循环中无条件退出,CONTINUE 关键字使 WHILE 循环跳过后面的语句,并重新开始循环。BREAK 关键字和 Oracle PL/SQL EXIT 关键字等同。Oracle 没有 CONTINUE 的对等关键字。

GOTO 语句

Oracle 和 Microsoft SQL Server 均有 GOTO 语句,但是语法不同。遇到 GOTO 语句,Transact-SQL 批处理执行就会跳到标号处。GOTO 语句和标号之间的语句不执行。

Oracle
Microsoft SQL Server

GOTO label;
<  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值