Oracle和SQLServer的语法区别

更新时间:2024-01-29 04:46:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Oracle和SQLServer的语法区别 SQL 语言支持

这一部分概述了 Transact-SQL 和 PL/SQL 语言语法之间的相同点和不同点,并给出转换策略。 要将 Oracle DML 语句和 PL/SQL 程序迁移到 SQL Server 时,请按下列步骤执行:

1. 验证所有 SELECT、INSERT、UPDATE 和 DELETE 语句的语法是有效的。进行任何必要的

修改。

2. 把所有外部联接改为 SQL-92 标准外部联接语法。 3. 用相应 SQL Server 函数替代 Oracle 函数。 4. 检查所有的比较运算符。

5. 用“+”字符串串联运算符代替“||”字符串串联运算符。 6. 用 Transact-SQL 程序代替 PL/SQL 程序。

7. 把所有 PL/SQL 游标改为非游标 SELECT 语句或 Transact-SQL 游标。 8. 用 Transact-SQL 过程代替 PL/SQL 过程、函数和包。 9. 把 PL/SQL 触发器转换为 Transact-SQL 触发器。 10. 使用 SET SHOWPLAN 语句,优化查询性能。

SELECT 语句

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

Oracle Microsoft SQL Server SELECT select_list SELECT [/*+ optimizer_hints*/] [INTO new_table_] [ALL | DISTINCT] select_list FROM table_source [FROM [WHERE search_condition] {table_name | view_name | [ GROUP BY [ALL] group_by_expression select_statement}] [,Un] [WHERE clause] [ WITH { CUBE | ROLLUP } ] [GROUP BY group_by_expression] [HAVING search_condition] [HAVING search_condition] [ORDER BY order_expression [ASC | [START WITH U CONNECT BY] DESC] ] [{UNION | UNION ALL | INTERSECT | In addition: MINUS} SELECT U] UNION Operator [ORDER BY clause] COMPUTE Clause [FOR UPDATE] 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 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 Microsoft SQL Server SELECT CCODE, CNAME FROM DEPT_ADMIN.CLASS C WHERE EXISTS (SELECT 'X' FROM STUDENT_ADMIN.GRADE G WHERE C.CCODE = G.CCODE) 在此例中,使用 MINUS 运算符,查找那些没有任何学生登记的课程。

Oracle 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 Microsoft SQL Server 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] INSERT INTO { {table_name | view_name | table_name [ [AS] table_alias] WITH select_statement} [(column_list)] ( [Un]) {values_list | select_statement} | 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 INSERT INTO (SELECT SSN, CCODE, GRADE FROM GRADE) VALUES ('111111111', '1111',NULL) Microsoft SQL Server 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 UPDATE {table_name | view_name | Microsoft SQL Server UPDATE { select_statement} table_name [ [AS] table_alias] WITH SET [column_name(s) = {constant_value ( [Un]) | expression | select_statement | view_name [ [AS] table_alias] column_list | | rowset_function_limited variable_list] } {where_statement} 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 DECLARE VAR1 NUMBER(10,2); BEGIN VAR1 := 2500; UPDATE STUDENT_ADMIN.STUDENT SET TUITION_TOTAL = VAR1; END; Microsoft SQL Server 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 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') Microsoft SQL Server 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 DELETE [FROM] {table_name | view_name | select_statement} [WHERE clause] Microsoft SQL Server 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 TRUNCATE TABLE table_name [{DROP | REUSE} STORAGE] Microsoft SQL Server 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 LEFT[OUTER] RIGHT[OUTER] FULL [OUTER] 为笛卡尔联接。 这种联接指定,所有内部行均要返回。丢弃任何不匹配的行。这和标准的 Oracle 表联接相同。 这种类型的联接指定,所有左表的外部行均要返回,即使没找到匹配的列,也就如此。这和 Oracle 外部联接 (+) 的操作类似。 这种类型的联接指定,所有右表的外部行均要返回,即使没找到匹配的列,也是如此。这和 Oracle 外部联接 (+) 的操作类似。 如果两个表中的一行不符合选择标准,则指定将这一行加到结果集中,并且将其对应于另一表的输出列设为 NULL。这和将 Oracle 外部联接运算符放在“=”号两边 (col1(+)=col2(+)) 的效果是一样的,但后者在 Oracle 中是不允许的。 下面的代码示例返回所有学生登记的课程列表。外部联接定义在学生 (student) 和成绩 (grade) 表之间,成绩表允许所有的学生出现在上面,甚至那些没有登记任何课程的学生也是如此。外部联接也加到课程表上,以返回课程名称。如果外部联接不加到课程表上,就不会返回那些没有登记任何课程的学生,因为他们的课程代码 (CCODE) 为空。

Oracle Microsoft SQL Server SELECT S.SSN AS SSN, SELECT S.SSN AS SSN, FNAME, LNAME FNAME, LNAME FROM STUDENT_ADMIN.GRADE G FROM STUDENT_ADMIN.STUDENT S, RIGHT OUTER JOIN DEPT_ADMIN.CLASS C, STUDENT_ADMIN.STUDENT S STUDENT_ADMIN.GRADE G ON G.SSN = S.SSN WHERE S.SSN = G.SSN(+) LEFT OUTER JOIN AND G.CCODE = C.CCODE(+) DEPT_ADMIN.CLASS C ON G.CCODE = C.CCODE 将 SELECT 语句做为表名使用

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

Oracle SELECT SSN, LNAME, FNAME, TUITION_PAID, SUM_PAID FROM STUDENT_ADMIN.STUDENT, (SELECT SUM(TUITION_PAID) SUM_PAID FROM STUDENT_ADMIN.STUDENT) 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) 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 绝对值 ABS 反余弦 ACOS 反正弦 ASIN n 的反正切 ATAN m/n 的反正切 ATAN2 >=值的最小整数 CEIL 余弦 COS 双曲余弦 COSH 指数值 EXP <=值的最大整数 FLOOR 自然对数 LN 以任何为底的对数 LOG(N) 以 10 为底的对数 LOG(10) 模数(余数) MOD 幂 POWER 随机数 暂缺 舍入 ROUND 数的符号 SIGN 正弦 SIN 双曲正弦 SINH 平方根 SQRT 正切 TAN 双曲正切 TANH 截尾 TRUNC 列表中的最大数 GREATEST 列表中的最小数 LEAST 如果为 NULL,转换成NVL 数字 Microsoft SQL Server ABS ACOS ASIN ATAN ATN2 CEILING COS COT EXP FLOOR LOG 暂缺 LOG10 USE MODULO (%) OPERATOR POWER RAND ROUND SIGN SIN 暂缺 SQRT TAN 暂缺 暂缺 暂缺 暂缺 ISNULL 字符函数

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

函数 Oracle 把字符转换成 ASCII ASCII 字符串串联 CONCAT 把 ASCII 转换成字CHR Microsoft SQL Server ASCII (表达式 + 表达式) CHAR

符 返回字符串中的起始INSTR 字符(从左) 将字符转换成小写 LOWER 将字符转换成大写 UPPER 在字符串的左边填充LPAD 字符 删除前导空格 LTRIM 删除尾空格 RTRIM 字符串中模式的起始INSTR 点 多次重复字符串 RPAD 字符串的语音表示 SOUNDEX 重复空格的字符串 RPAD 从数字数据转换而来TO_CHAR 的字符数据 子串 SUBSTR 字符替换 REPLACE 字符串中每个词的第INITCAP 一个字母大写 字符串转换 TRANSLATE 字符串长度 LENGTH 列表中的最大字符串 GREATEST 列表中的最小字符串 LEAST 如果为 NULL,则转换NVL 字符串 CHARINDEX LOWER UPPER 暂缺 LTRIM RTRIM PATINDEX REPLICATE SOUNDEX SPACE STR SUBSTRING STUFF 暂缺 暂缺 DATELENGTH 或 LEN 暂缺 暂缺 ISNULL 日期函数

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

函数 日期加 日期间的间隔 当前日期和时间 月的最后一天 时区转换 该日期后的第一个工NEXT_DAY 作日 Oracle (日期列 +/- 值)或 ADD_MONTHS (日期列 +/- 值)或 MONTHS_BETWEEN SYSDATE LAST_DAY NEW_TIME Microsoft SQL Server DATEADD DATEDIFF GETDATE() 暂缺 暂缺 暂缺 日期的字符串表示 TO_CHAR DATENAME 日期的整数表示 TO_NUMBER (TO_CHAR)) DATEPART 日期舍入 ROUND CONVERT 日期截尾 TRUNC CONVERT 字符串转换为日期 TO_DATE CONVERT 如果为 NULL,则转换NVL ISNULL 日期 转换函数

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

函数 数字到字符 字符到数字 日期到字符 字符到日期 十六进制到二进制 二进制到十六进制 Oracle TO_CHAR TO_NUMBER TO_CHAR TO_DATE HEX_TO_RAW RAW_TO_HEX Microsoft SQL Server CONVERT CONVERT CONVERT CONVERT CONVERT CONVERT 其它行级函数

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

函数 Oracle 返回第一个非空表达DECODE 式 当前序列值 CURRVAL 下一个序列值 NEXTVAL 如果表达式 1 = 表达DECODE 式 2,则返回空 用户的登录 ID 号 UID 用户的登录名 USER 用户的数据库 ID 号 UID 用户的数据库名 USER 当前用户 CURRENT_USER 用户环境(审核记录) USERENV CONNECT BY 子句的级LEVEL 别 Microsoft SQL Server COALESCE 暂缺 暂缺 NULLIF SUSER_ID SUSER_NAME USER_ID USER_NAME CURRENT_USER 暂缺 暂缺 合计函数

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

函数 平均值 计数 最大值 最小值 标准偏差 汇总 方差 Oracle AVG COUNT MAX MIN STDDEV SUM VARIANCE Microsoft SQL Server AVG COUNT MAX MIN STDEV 或 STDEVP SUM VAR 或 VARP 条件测试

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

Oracle 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 Microsoft SQL Server 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 ,'D+', 1.3 ,'D-', 0.7 ,0)),2) FROM STUDENT_ADMIN.GRADE GROUP BY SSN 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 字符到数字 TO_NUMBER('10') 数字到字符 TO_CHAR(10) Microsoft SQL Server CONVERT(numeric, '10') CONVERT(char, 10) CONVERT(datetime, TO_DATE('04-JUL-97') '04-JUL-97') TO_DATE('04-JUL-1997', CONVERT(datetime, 字符到日期 'dd-mon-yyyy') '04-JUL-1997') TO_DATE('July 4, 1997', CONVERT(datetime, 'July 4, 'Month dd, yyyy') 1997') TO_CHAR(sysdate) CONVERT(char, GETDATE()) TO_CHAR(sysdate, 'dd mon CONVERT(char, GETDATE(), 日期到字符 yyyy') 106) TO_CHAR(sysdate, CONVERT(char, GETDATE(), 'mm/dd/yyyy') 101) 十六进制到HEXTORAW('1F') CONVERT(binary, '1F') 二进制 二进制到十RAWTOHEX CONVERT(char, 六进制 (binary_column) binary_column) 注意,字符串是如何转换成日期的。在 Oracle 中,默认的日期格式模型为“DD-MON-YY”。如果使用任何其它格式,必须提供相应的日期格式模型。CONVERT 函数自动转换标准日期格式,而无须格式模型。

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

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

不带世纪 - 1 2 3 4 5 6 7 8 - 10 11 12 - 14 带有世纪 标准 0 或 100 (*) 默认 101 102 103 104 105 106 107 108 美国 ANSI 英国/法国 德国 意大利 - - - 9 或 109 (*) 默认毫秒 110 111 112 美国 日本 ISO 13 或 113 (*) 欧洲默认 114 - 输出 mon dd yyyy hh:miAM(或 PM) mm/dd/yy yy.mm.dd dd/mm/yy dd.mm.yy dd-mm-yy dd mon yy mon dd, yy hh:mm:ss mon dd yyyy hh:mi:ss:mmm(AM 或 PM) mm-dd-yy yy/mm/dd yymmdd dd mon yyyy hh:mm:ss:mmm(24h) hh:mi:ss:mmm(24h) 用户定义的函数

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

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

Oracle SELECT SSN, FNAME, LNAME, ) TUITION_PAID, Microsoft SQL Server SELECT SSN, FNAME, LNAME, TUITION_PAID,

TUITION_PAID/GET_SUM_ MAJOR(MAJOR) AS PERCENT_MAJOR FROM STUDENT_ADMIN.STUDENT 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 不需要 CREATE FUNCTION 语法;使SELECT SUM(TUITION_PAID) INTO 用 CREATE PROCEDURE 语法。 SUM_PAID FROM STUDENT_ADMIN.STUDENT WHERE MAJOR = INMAJOR; RETURN(SUM_PAID); END GET_SUM_MAJOR; Oracle 和 Microsoft SQL Server 比较运算符几乎是相同的。

运算符 Oracle Microsoft SQL Server 等于 (=) (=) 大于 (>) (>) 小于 (<) (<) 大于或等于 (>=) (>=) 小于或等于 (<=) (<=) 不等于 (!=, <>, ^=) (!=, <>, ^=) 不大于,不小于 暂缺 !> , !< 在集合的任何成员中 IN IN 不在集合的任何成员NOT IN NOT IN 中 集合中的任一值 ANY, SOME ANY, SOME != ALL, <> ALL, < ALL, != ALL, <> ALL, < ALL, > ALL, <= ALL, >= > ALL, <= ALL, >= 引用集合中的 ALL, != SOME, <> SOME, ALL, != SOME, <> SOME, 所有值 < SOME, > SOME, < SOME, > SOME, <= SOME, >= SOME <= SOME, >= SOME 与模式相似 LIKE LIKE 与模式不相似 NOT LIKE NOT LIKE x 和 y 之间的值 BETWEEN x AND y BETWEEN x AND y 不在两者之间的值_ NOT BETWEEN 值存在 EXISTS 值不存在 NOT EXISTS 值{为|不为} NULL NOT BETWEEN EXISTS NOT EXISTS 相同。也可以使用 = NULL、 IS NULL, IS NOT NULL !=NULL,用于向后兼容性(不推荐使用)。 模式匹配

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

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

Oracle SELECT * FROM STUDENT_ADMIN.STUDENT WHERE LNAME LIKE 'A%' OR LNAME LIKE 'B%' OR LNAME LIKE 'C%' Microsoft SQL Server 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 SELECT FNAME +' '+ LNAME AS NAME NAME FROM STUDENT_ADMIN.STUDENT FROM STUDENT_ADMIN.STUDENT 控制流语言控制 SQL 语句、语句块和存储过程的执行数据流。PL/SQL 和 Transact SQL 提供了许多相同的结构,但在语法上有一些差异。

关键字

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

语句 声明变量 语句块 Oracle PL/SQL DECLARE BEGIN...END; IFUTHEN, ELSIFUTHEN, ELSE ENDIF; 条件处理 无条件退出 RETURN 无条件退出到当前程序块结束后紧接着的EXIT BREAK 那条语句 重新开始一个 WHILE 暂缺 CONTINUE 循环 暂缺 等待指定的间隔 WAITFOR (dbms_lock.sleep) WHILE LOOPUEND LOOP; WHILE BEGINU END 循环控制 LABELUGOTO LABEL; FORUEND LOOP; LABELUGOTO LABEL LOOPUEND LOOP; 程序注释 /* U */, -- /* U */, -- 打印输出 RDBMS_OUTPUT.PUT_ PRINT Microsoft SQL Server Transact-SQL DECLARE BEGIN...END IFU[BEGINUEND] ELSE [BEGINUEND] ELSE IF CASE expression RETURN 提出程序错误 执行程序 语句终止符 LINE RAISE_APPLICATION_ ERROR EXECUTE 分号 (;) RAISERROR EXECUTE 暂缺 声明变量

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

Oracle DECLARE VSSN CHAR(9); VFNAME VARCHAR2(12); VLNAME VARCHAR2(20); VBIRTH_DATE DATE; VLOAN_AMOUNT NUMBER(12,2); Microsoft SQL Server 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 赋值运算符 (:=) 用于从一行中选择列值的 SELECT...INTO 语法。 FETCHUINTO 语法 以下是一些语法示例。

Microsoft SQL Server SET @local_variable = value SELECT @local_variable = expression [FROMU] 用于为字面值、涉及其它局部变量的表达式或一行中的列值赋值。 FETCHUINTO 语法 Oracle DECLARE VSSN CHAR(9); 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; @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 DECLARE VARIABLES ... DECLARE VARIABLES ... BEGIN -- THIS IS OPTIONAL SYNTAX BEGIN -- THIS IS REQUIRED SYNTAX PROGRAM_STATEMENTS ... PROGRAM_STATEMENTS ... IF ... IF ...THEN BEGIN STATEMENT1; STATEMENT1 STATEMENT2; STATEMENT2 STATEMENTN; STATEMENTN END IF; END WHILE ...LOOP WHILE ... STATEMENT1; BEGIN STATEMENT2; STATEMENT1 STATEMENTN; STATEMENT2 END LOOP; STATEMENTN END; -- THIS IS REQUIRED SYNTAX END END -- THIS IS REQUIRED SYNTAX 条件处理

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

Oracle DECLARE Microsoft SQL Server DECLARE

VDEGREE_PROGRAM CHAR(1); @VDEGREE_PROGRAM CHAR(1), VDEGREE_PROGRAM_NAME @VDEGREE_PROGRAM_NAME VARCHAR2(20); VARCHAR(20) BEGIN SELECT @VDEGREE_PROGRAM = 'U' VDEGREE_PROGRAM := 'U'; SELECT @VDEGREE_PROGRAM_ IF VDEGREE_PROGRAM = 'U' THEN NAME = CASE @VDEGREE_PROGRAM VDEGREE_PROGRAM_NAME := WHEN 'U' THEN 'Undergraduate' 'Undergraduate'; WHEN 'M' THEN 'Masters' ELSIF VDEGREE_PROGRAM = 'M' WHEN 'P' THEN 'PhD'. THEN VDEGREE_PROGRAM_ ELSE 'Unknown' NAME := 'Masters'; END ELSIF VDEGREE_PROGRAM = 'P' THEN VDEGREE_PROGRAM_ NAME := 'PhD'; ELSE VDEGREE_PROGRAM_ NAME := 'Unknown'; END IF; END; 重复的语句执行(循环)

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

{sql_statement | statement_block} [BREAK] [CONTINUE]

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

Oracle DECLARE COUNTER NUMBER; BEGIN COUNTER := 0 WHILE (COUNTER <5) LOOP COUNTER := COUNTER + 1; END LOOP; END; Microsoft SQL Server 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 GOTO label; <

Transact-SQL PRINT 语句和 PL/SQL RDBMS_OUTPUT.put_line 过程所执行的操作相同。它用于打印用户指定的消息。

PRINT 语句的消息限度为 8,000 个字符。使用 char 或 varchar 数据类型定义的变量可以嵌入打印语句中。如果使用了任何其它数据类型,必须使用 CONVERT 或 CAST 函数。可以打印局部变量、全局变量和文本。可用单引号和双引号将文本括上。

从存储过程返回

Microsoft SQL Server 和 Oracle 均有 RETURN 语句。使用 RETURN 语句,程序可从查询或过程无条件退出。RETURN 是一条可立即执行的完整语句,并可在任何时候用于从过程、批处理或语句块中退出。RETURN 后面的语句均不执行。

Oracle RETURN expression: Microsoft SQL Server RETURN [integer_expression] 提出程序错误

Transact-SQL RAISERROR 语句返回一个用户定义的错误信息,并设定一个系统标志,来记录已发生了一个错误。它和 PL/SQL raise_application_error 异常错误处理程序的功能相似。 RAISERROR 语句允许客户从 sysmessages 表检索一个条目,或使用用户定义的严重性和状态信息动态地创建一条消息。定义后,此消息作为服务器错误信息返回给客户。

RAISERROR ({msg_id | msg_str}, severity, state [, argument1 [, argument2]]) [WITH options]

转换 PL/SQL 程序时,可能不需要使用 RAISERROR 语句。在下面的代码示例中,PL/SQL 程序使用 raise_application_error 异常错误处理程序,而 Transact-SQL 程序什么也不使用。加入 raise_application_error 异常错误处理程序,可避免 PL/SQL 程序返回二义性的 unhandled exception 错误信息。相反,当发生意外问题时,它总是返回 Oracle 错误信息 (SQLERRM)。

当 Transact-SQL 程序失败时,它总是给客户程序返回详细的错误信息。因此,除非需要进行专门错误处理,否则,并不总是需要 RAISERROR 语句。

Oracle CREATE OR REPLACE FUNCTION DEPT_ADMIN.DELETE_DEPT (VDEPT IN VARCHAR2) RETURN NUMBER AS BEGIN DELETE FROM DEPT_ADMIN.DEPT WHERE DEPT = VDEPT; RETURN(SQL%ROWCOUNT); EXCEPTION WHEN OTHER THEN RAISE_APPLICATION_ERROR (-20001,SQLERRM); END DELETE_DEPT; / Microsoft SQL Server CREATE PROCEDURE DEPT_ADMIN.DELETE_DEPT @VDEPT VARCHAR(4) AS DELETE FROM DEPT_DB.DBO.DEPT WHERE DEPT = @VDEPT RETURN @@ROWCOUNT GO 游标的实现

不管从数据库中请求行数的多少,Oracle 始终要求游标和 SELECT 语句一起使用。在 Microsoft SQL Server 中,未包含在游标内的 SELECT 语句把行作为默认结果集,返回给客户。这是一种将数据返回给客户程序的有效方法。

SQL Server 给游标函数提供了两个接口。当在 Transact-SQL 批处理或存储过程时使用游标时,SQL 语句可用来声明、打开游标和从游标以及定位更新和删除中提取。当使用来自 DB-Library、ODBC 或 OLE DB 的游标时,SQL Server 客户机库透明地调用内置的服务器函数,以更有效地处理游标。

当从 Oracle 导入 PL/SQL 过程时,首先确定游标是否需要执行和 Transact-SQL 中相同的功能。如果游标只给客户程序返回一组行,则使用 Transact-SQL 中无游标的 SELECT 语句,返回一个默认的结果集。如果使用游标向局部过程变量每次加载一行数据,则必须使用 Transact-SQL 中的游标。

下表给出了游标的使用语法。

操作 Microsoft SQL Server DECLARE cursor_name CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | CURSOR cursor_name DYNAMIC | 声明游标 [(cursor_parameter(s))] FAST_FORWARD] IS select_statement; [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] [TYPE_WARNING] FOR select_statement [FOR UPDATE [OF column_name [,Un]]] OPEN cursor_name 打开游标 OPEN cursor_name [(cursor_parameter(s))]; FETCH [[NEXT | PRIOR | FIRST | LAST | ABSOLUTE {n | @nvar} FETCH cursor_name INTO 从游标中提取 | RELATIVE {n | variable(s) @nvar}] FROM] cursor_name [INTO @variable(s)] UPDATE table_name UPDATE table_name SET statement(s)U SET statement(s)U 更新提取的行 WHERE CURRENT OF WHERE CURRENT OF cursor_name; cursor_name DELETE FROM DELETE FROM table_name table_name 删除提取的行 WHERE CURRENT OF WHERE CURRENT OF cursor_name; cursor_name 关闭游标 CLOSE cursor_name; CLOSE cursor_name DEALLOCATE 删除游标数据结构 暂缺 cursor_name 尽管 Transact-SQL DECLARE CURSOR 语句不支持使用游标参数,但它的确支持局部变量。当游标打开时,这些局部变量的值可在游标中使用。Microsoft SQL Server 在其 DECLARE CURSOR 语句中提供了许多额外的功能。

Oracle INSENSITIVE 选项用于定义游标,使之创建一个要使用的数据的临时副本。对游标的所有请求均由此临时表应答。因此,对基表的修改不会反映在对该游标提取所返回的数据中。这种类型游标访问的数据不能被修改。

应用程序可以请求一种游标类型,然后执行一条不被所请求类型服务器游标支持的

Transact-SQL 语句。SQL Server 就会返回一个错误,指出游标类型已经更改;或者如给定了一组要素,SQL Server 就会隐式转换游标。有关使 SQL Server 7.0 隐式地将游标从一种类型转换到另一种类型的完整要素列表,请参见 SQL Server Books Online。

除向前提取外,SCROLL 选项还允许向后、绝对和相对提取。滚动游标使用键集游标模型,在该模型中,任何用户对基表的已提交删除和更新都会反映在以后的提取中。仅当没有使用 INSENSITIVE 选项来声明该游标时,才成立。

如果选定了 READ ONLY 选项,则禁止对游标中的任何行进行更新。该选项将改写对游标更新的默认功能。

UPDATE [OF column_list] 语句用于定义游标中可更新的列。如果给出了 [OF column_list],则只有列出的列允许修改。如果没有给出列表,所有的列均可更新,除非游标已定义为 READ ONLY。

注意到,SQL Server 游标的名称作用域就是连接本身这一点,是很重要的。这和局部变量的名称作用域不同。在同一用户连接上,在第一个游标释放之前,不能声明与现有游标名称相同的第二个游标。

与 PL/SQL 不同,在一个游标打开时,Transact-SQL 不支持向该游标传递参数。当 Transact-SQL 游标打开时,结果集成员身份和次序是固定的。对于其他用户已提交的对基表的更新和删除,均会反映在所有未使用 INSENSITIVE 选项定义的游标提取中。对于 INSENSITIVE 游标,还会生成一个临时表。

Oracle 游标只能向前移动--不能向后或相对滚动。SQL Server 可以使用下表所示的提取选项,向前和向后滚动。只有当游标使用 SCROLL 选项声明时,这些提取选项才可以使用。

滚动选项 NEXT PRIOR FIRST LAST ABSOLUTE n RELATIVE n 说明 如果是对游标的提取,返回结果集的第一行,如果不是,在结果集中移动游标一行。NEXT 是在结果集中移动所使用的主要方法。NEXT 是默认的游标提取。 在结果集中,返回上一行。 把游标移动到结果集的第一行,并返回第一行。 把游标移动到结果集的最后一行,并返回最后一行。 返回结果集中的第 n 行。如果 n 是负值,则返回的行是从结果集最后一行向回数的第 n 行。 返回当前提取行后的第 n 行。如果 n 是负值,返回的行是从游标的相对位置向回数的第 n 行。

Transact-SQL FETCH 语句不需要 INTO 子句。如果没有指定返回变量,该行就会作为单行结果集,自动返回给客户。但是,如果过程必须给客户提供行,则使用无游标的 SELECT 语句,更为有效。

在每个 FETCH 之后,@@FETCH_STATUS 函数均被更新。它和 PL/SQL 中使用的 CURSOR_NAME%FOUND 和 CURSOR_NAME%NOTFOUND 变量用法类似。每次成功提取后,

@@FETCH_STATUS 函数值被设为 0。如果该提取要读取游标结尾之外的地方,则返回值 -1。如果游标打开后,请求的行已被从表中删除,则 @@FETCH_STATUS 函数返回 -2。通常,返回值 -2 只在使用 SCROLL 选项声明的游标中出现。每次提取后,必须检查该变量,以保证数据的有效性。 SQL Server 不支持 Oracle 的游标 FOR 循环语法。

在 PL/SQL 和 Transact-SQL 中,用于更新和删除的 CURRENT OF 子句语法和函数是相同的。定位 UPDATE 或 DELETE 用于对指定游标内的当前行进行更新和删除操作。

Transact-SQL CLOSE CURSOR 语句关闭游标,但数据结构仍可用于重新打开游标。PL/SQL CLOSE CURSOR 语句关闭并释放所有的数据结构。

Transact-SQL 需要使用 DEALLOCATE CURSOR 语句,删除游标数据结构。DEALLOCATE CURSOR 语句与 CLOSE CURSOR 的不同之处在于,关闭的游标可以重新打开。DEALLOCATE CURSOR 语句释放所有与游标有关的数据结构,并删除游标的定义。

下面示例给出了,PL/SQL 和 Transact-SQL 中对等的游标语句。

Oracle DECLARE VSSN CHAR(9); VFNAME VARCHAR(12); VLNAME VARCHAR(20); Microsoft SQL Server DECLARE @VSSN CHAR(9), @VFNAME VARCHAR(12), @VLNAME VARCHAR(20) CURSOR CUR1 IS DECLARE curl CURSOR FOR SELECT SSN, FNAME, LNAME SELECT SSN, FNAME, LNAME FROM STUDENT ORDER BY LNAME; FROM STUDENT ORDER BY SSN BEGIN OPEN CUR1 OPEN CUR1; FETCH NEXT FROM CUR1 FETCH CUR1 INTO VSSN, VFNAME, INTO @VSSN, @VFNAME, @VLNAME VLNAME; WHILE (@@FETCH_STATUS <> -1) WHILE (CUR1%FOUND) LOOP BEGIN FETCH CUR1 INTO VSSN, VFNAME, FETCH NEXT FROM CUR1 INTO @VSSN, VLNAME; @VFNAME, @VLNAME END LOOP; END CLOSE CUR1; CLOSE CUR1 END; DEALLOCATE CUR1 优化 SQL 语句

本节提供了用于优化 Transact-SQL 语句的一些 SQL Server 工具的信息。有关优化 SQL Server 数据库的详细信息,请参见本卷前面的“性能优化”。

可以使用 SQL Server 查询分析器的图形显示计划功能,了解优化程序处理语句的详细信息。 此图形工具可以实时地捕获服务器活动的连续记录。SQL Server 事件探查器监视多个不同的服务器事件和事件类别,使用用户定义的标准筛选这些事件,并把跟踪记录输出到屏幕、文件或其它 SQL Server。

SQL Server 事件探查器可用于:

? ? ? ? ? ?

监视 SQL Server 的性能。

调试 Transact-SQL 语句和存储过程。 确定执行缓慢的查询。

解决 SQL Server 中的问题。通过捕获引起某一特定问题的所有事件,然后在测试系统上重现这些事件,以重复和分离该问题,达到解决问题的目的。

在项目开发阶段,通过单步执行语句,每次一行,测试 SQL 语句和存储过程,来确认代码是否按照预期结果执行。

在生产系统上捕获事件,并在测试系统上重现所捕获的那些事件,从而为测试或调试重建了生产环境中所发生的事件。通过在其它系统中重现所捕获的事件,用户可继续使用生产系统,而不会影响正常工作。

SQL Server 事件探查器给一组扩展存储过程提供了图形用户界面。也可以直接使用这些扩展存储过程。因此,可以创建自己的应用程序,它使用 SQL Server 事件探查器扩展存储过程监视 SQL Server。

SET 语句可以为工作会话期、触发器或存储过程运行期设定 SQL Sever 查询处理选项。 SET FORCEPLAN ON 语句强制优化程序按照表在 FROM 子句中出现的顺序处理联接,类似 Oracle 优化程序中使用的 ORDERED 提示。

SET SHOWPLAN_ALL 和 SET SHOWPLAN_TEXT 语句只返回查询或语句的执行计划信息,但不执行查询或语句。要运行查询或语句,将相应的显示计划语句设为 OFF。然后,查询或语句就会执行。SHOWPLAN 选项与 Oracle EXPLAIN PLAN 工具提供的结果类似。

使用 SET STATISTICES PROFILE ON,每个执行的查询返回标准的结果集,然后,返回附加结果集(给出查询执行的事件探查)。其它选项包括 SET STATISTICS IO 和 SET STATISTIECS TIME。 Transact-SQL 语句处理包括分两步,即编译和执行。NOEXEC 选项编译每个查询,但不执行。NOEXEC 设为 ON 时,不执行随后的语句(包括其它 SET 语句),直到 NOEXEC 设为 OFF 为止。 SET SHOWPLAN ON SET NOEXEC ON

go

SELECT * FROM DEPT_ADMIN.DEPT, STUDENT_ADMIN.STUDENT WHERE MAJOR = DEPT go STEP 1

The type of query is SETON STEP 1

The type of query is SETON STEP 1

The type of query is SELECT FROM TABLE DEPT_ADMIN.DEPT Nested iteration Table Scan FROM TABLE

STUDENT_ADMIN.STUDENT Nested iteration Table Scan

Oracle 需要使用提示,来调整基于开销的优化程序的操作和性能。Microsoft SQL Server 基于开销的优化程序不需要使用提示,来协助其查询评估过程。但是在某些情况下,确有使用它们的必要。

INDEX = {index_name | index_id} 提示指定了该表使用的索引名或 ID。 index_id 为 0,就会强制一个表扫描,而当 index_id 为 1,则强制使用聚集索引(如存在)。这和 Oracle 中使用的索引提示类似。

如果其列顺序和 ORDER BY 子句匹配,SQL Server FASTFIRSTROW 提示就会指示优化程序使用非聚集索引。这个提示的运行方式和 Oracle FIRST_ROWS 提示类似。

定义数据库对象

Oracle 数据库对象(表、视图和索引)可以很方便地迁移到 Microsoft SQL Server,因为每种 RDBMS 都严格遵循 SQL-92 标准,该标准是一个关于对象定义的标准。将 Oracle SQL 表、索引和视图定义转换为 SQL Server 表、索引和视图定义,只需要进行相对简单的语法更改即可。下表着重阐述了,Oracle 和 Microsoft SQL Server 数据库对象之间的一些差异。

类别 列数 行大小 Microsoft SQL Server Oracle 1024 254 8060 字节,加 16 字节指向每个 没有限制(但每行只允许一个 long 或 long raw) 最大行数 没有限制 没有限制 每表一个 long 或 和行一起存储的 16 字节指针。long raw。必须在行BLOB 类型存储 数据存储在其它数据页上。 尾。数据存储在与行相同的块上。 每表一个(索引组织的聚集的表索引 每表一个 表) 非聚集的表索引 每表 249 个 没有限制 单索引中索引的16 16 最大列数 索引中列值的最900 字节 1/2 块 大长度 [[[server.]database.]owner.] 表命名规则 [schema.]table_name table_name [[[server.]database.]owner.] 视图命名规则 [schema.]table_name table_name [[[server.]database.]owner.] 索引命名规则 [schema.]table_name table_name 假定您从用来创建数据库对象的 Oracle SQL 脚本或程序入手。只要复制这个脚本或程序,并进行下列修改即可。每个更改均在本节的其它部分进行了讨论。该例取自脚本示例程序脚本 Oratable.sql 和 Sstable.sql。

1. 确保数据库对象标识符符合 Microsoft SQL Server 命名规则。可能只需要更改索引名

称。

2. 修改数据存储参数,使之用于 SQL Server。如果使用 RAID,则不需要存储参数。 3. 修改 Oracle 约束定义,使之用于 SQL。如有必要,则创建触发器,以支持外键 DELETE

CASCADE 语句。如果表跨几个数据库,则使用触发器强制外键关系。 4. 修改 CREATE INDEX 语句,以使用聚集索引。

5. 使用“数据转换服务”,创建新的 CREATE TABLE 语句。检查该语句,注意 Oracle 数

据类型与 SQL Server 数据类型是如何对应的。

6. 删除所有 CREATE SEQUENCE 语句。在 CREATE TABLE 或 ALTER TABLE 语句中,使用标

识符列,替代序列的使用。

7. 如有必要,修改 CREATE VIEW 语句。 8. 删除任何对同义词的引用。

9. 评估 Microsoft SQL Server 临时表的使用,及其在应用程序中的用途。

10. 把 Oracle 的所有 CREATE TABLEUAS SELECT 命令改成 SQL Server 的 SELECTUINTO 语

句。

11. 评估用户定义的规则、数据类型和默认值的潜在用途。

下面图表比较了,Oracle 和 Microsoft SQL Server 处理对象标识符的方式。在大多数情况下,向 SQL Server 迁移时,不需要更改对象名称。

text 或 image 列 Oracle Microsoft SQL Server 1-30 个字符长。 数据库名称:最多 8 个字符长。 1-128 个 Unicode 字符长。 数据库链接名称:最多 128 个字临时表名称:最多 116 个字符长。 符长。 标识符名称可以以字母数字字符或 _ 开头,并且几乎可包含任何字符。 如果标识符以空格开始,并包含除 _、标识符名称必须以字母开头,并包@、# 或 $ 以外的字符,则必须使用 含字母、数字字符或 _、$、和 # 字[](分隔符)将标识符名称括起来。 符。 如果对象开始字符是: @ 它是一个局部变量。 # 它是一个局部临时对象。 ## 它是一个全局临时对象。 表空间名称必须唯一。 数据库名称必须唯一。 在用户帐户(架构)中,标识符名在数据库用户帐户中,标识符名称必称必须是唯一的。 须是唯一的。 在表或视图中,列名必须是唯一在表或视图中,列名必须是唯一的。 的。 在用户架构中,索引名称必须是唯在数据库表名称中,索引名称必须是一的。 唯一的。 当访问 Oracle 用户帐户中的表时,仅按其不合格的名称来选定它。访问其它 Oracle 架构中的表时,在表名称前加上架构名称和一个英文句点 (.)。Oracle 同义词可提供其它的位置透明性。 当 Microsoft SQL Server 引用表时,使用了另一套命名规则。因为 SQL Server 登录帐户可以在多个数据库中使用同一名称创建表,所以可使用下列规则访问表和视图:[[database_name.]owner_name.]table_name

访问以下项中的Oracle 表 用户帐户 SELECT * FROM STUDENT SELECT * FROM STUDENT_ADMIN.STUDENT Microsoft SQL Server SELECT * FROM USER_DB.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 进行如下查询:

1. STUDENT_DB.current_user.STUDENT 2. STUDENT_DB.DBO.STUDENT

如果用户一次只使用一个数据库,在对象的引用中省略数据库名称,这样,在其它数据库中使用该应用程序就变得简单了。所有对象引用隐式访问当前使用的数据库。如果在同一服务器上,要维护一个测试数据库和一个生产数据库,这是很有用的。

因为 Oracle 和 SQL Server 均支持标识 RDBMS 对象的 SQL-92 初级规则,所以,CREATE TABLE 语法是相似的。

Oracle CREATE TABLE [schema.]table_name Microsoft SQL Server CREATE TABLE [server.][database.][owner.] ( table_name {col_name column_properties ( [default_expression] {col_name [constraint [constraint column_properties[constraint [...constraint]]]| [[,] [constraint [...constraint]]]| constraint]} [[,] constraint]} [[,] {next_col_name | [[,] {next_col_name | next_constraint}...] next_constraint}...] ) ) [Oracle Specific Data Storage [ON filegroup_name] Parameters] Oracle 数据库对象名称不区分大小写。在 Microsoft SQL Server 中,取决所选的安装选项,数据库对象名可以是区分大小写的。

SQL Server 第一次安装时,默认的排序次序是字典顺序、不区分大小写。(可以使用 SQL Server 安装程序,设定不同的配置。)因为 Oracle 对象名称始终是唯一的,所以,把数据库对象迁移到 SQL Server,不应有任何问题。建议在 Oracle 和 SQL Server 中所有的表和列名都使用大写,以避免用户在区分大小写的 SQL Server 上安装时出现问题。

有了 Microsoft SQL Server,使用 RAID 通常可简化数据库对象的存放。与 Oracle 索引组织的表一样,SQL Server 聚集索引被集成到表的结构中。

Oracle Microsoft SQL Server 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 CREATE TABLE USER_DATA USER_DB.DEPT_ADMIN.DEPT ( PCTFREE 0 STORAGE (INITIAL 10K DEPT VARCHAR(4) NOT NULL, NEXT 10K DNAME VARCHAR(30) NOT NULL, MINEXTENTS 1 MAXEXTENTS CONSTRAINT DEPT_DEPT_PK UNLIMITED), PRIMARY KEY CLUSTERED (DEPT), CONSTRAINT DEPT_DNAME_UNIQUE CONSTRAINT DEPT_DNAME_UNIQUE UNIQUE (DNAME) UNIQUE NONCLUSTERED (DNAME) USING INDEX TABLESPACE ) USER_DATA PCTFREE 0 STORAGE (INITIAL 10K NEXT 10K MINEXTENTS 1 MAXEXTENTS UNLIMITED) ) PCTFREE 10 PCTUSED 40 TABLESPACE USER_DATA STORAGE (INITIAL 10K NEXT 10K MINEXTENTS 1 MAXEXTENTS UNLIMITED FREELISTS 1) 在 Oracle 中,可以使用任何有效的 SELECT 命令,来创建表。Microsoft SQL Server 可提供相同的功能,但语法不同。

Oracle Microsoft SQL Server CREATE TABLE STUDENTBACKUP AS SELECT * INTO STUDENTBACKUP SELECT * FROM STUDENT FROM STUDENT 除非要应用的数据库已将 select into/bulkcopy 数据库配置选项设为 ture,否则,SELECTUINTO 不会生效。(数据库所有者可以使用 SQL Server Enterprise Manager 或 Transact-SQL sp_dboption 系统存储过程设定该选项。)使用 sp_helpdb 系统存储过程检查数据库的状态。如果 select into/bulkcopy 没有设为 true,仍可使用 SELECT 语句,将数据复制到一个临时表中。

SELECT * INTO #student_backup FROM user_db.student_admin.student

当使用 SELECT..INTO 语句创建新表时,引用完整性定义并没有被转移到新表中。

必须把 select into/bulkcopy 选项设为 true,这一需求可能使迁移过程变得复杂。如果必须使用 SELECT 语句把数据复制到表中,先创建表,然后使用 INSERT INTOUSELECT 语句加载表。Oracle 和 SQL Server 的语法是一致的,并且不需要设定任何数据库选项。 在 Microsoft SQL Server 中,用于创建视图的语法与 Oracle 相似。

Oracle Microsoft SQL Server CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW [schema.]view_name CREATE VIEW [owner.]view_name [(column_name [, [(column_name [, column_name]...)] column_name]...)] [WITH ENCRYPTION] AS select_statement AS select_statement [WITH CHECK [WITH CHECK OPTION [CONSTRAINT OPTION] name]] [WITH READ ONLY] SQL Server 的视图要求该表存在,并且视图所有者有权访问 SELECT 语句中所指定的表(与 Oracle FORCE 选项类似)。

默认情况下,并不检查视图上的数据修改语句,来确定受影响的行是否在视图的作用域内。要检查所有的修改,则使用 WITH CHECK OPTION。WITH CHECK OPTION 的主要差异在于,Oracle 将其定义为一个约束,而 SQL Server 没有。其它方面,两者是相同的。

定义视图时,Oracle 提供了 WITH READ ONLY 选项。通过将 SELECT 权限仅授予视图用户,SQL Server 应用程序也可获得相同的结果。

SQL Server 和 Oracle 视图均支持使用数学表达式、函数和常量表达式创建派生列。一些 SQL Server 特定的差异有:

? ? ? ?

如果数据修改语句只影响一个基表,则可在多个视图上允许使用数据修改语句(INSERT 或 UPDATE)。在一个语句中,数据修改语句不能用于多于一个表。 视图中的 text 或 image 列不能使用 READTEXT 或 WRITETEXT。 不能使用 ORDER BY、COMPUTE、FOR BROWSE 或 COMPUTE BY 子句。 视图中不能使用 INTO 关键字。

当一个视图是由外部联接定义的,并使用该联接内表一个列上的限定条件进行查询时,SQL Server 和 Oracle 给出的结果可能不同。在大多数情况下,Oracle 视图可以方便地转成 SQL Server 视图。

Oracle 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 Microsoft SQL Server 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 Microsoft SQL Server 提供聚集和非聚集的索引结构。这些索引由页组成,页又构成称为“B 树”的分支结构(类似于 Oracle B 树索引结构)。起始页(根级)指定了表中值的范围。根级

页的每个范围都指向另一页(决定节点),它包含的表值范围更窄。依次,这些决定节点可以指向其它决定节点,进一步缩小搜索范围。分支结构的最终级别称为叶级。

聚集索引

在 Oracle 中,聚集索引实现为用索引组织的表。聚集索引与表物理地结合在一起。表和索引共享同一存储区域。聚集索引按照索引的顺序物理地重排数据行,构成中间决定节点。索引的叶级页包含实际的表数据。这种结构只允许每个表一个聚集索引。一旦在表上施加了 PRIMARY KEY 或 UNIQUE 约束,Microsoft SQL Server 就会自动为该表创建一个聚集索引。聚集索引用于:

? ? ?

主键

未被更新的列

使用 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(姓、名)上可以创建聚集索引,因为这是将学生分组的常用方法。 ?

将一个表上的活动进行分布,以防止出现“热点”。热点通常是由于多个用户使用升序键对一个表插入造成的。这种应用场景通常用行级锁定来处理。

在 SQL Server 中,删除和重新创建聚集索引是重组表的一种常用技巧。使用这种方法,可以很容易地保证,在磁盘上页是连续的,且可以在表上方便地重建一些可用空间。这与 Oracle 中的导出、删除和导入表类似。

SQL Server 聚集索引和 Oracle 聚集没有任何相同之处。Oracle 聚集是两个或多个表的物理组合,这些表共享相同的数据块,并使用公共列作为聚集键。在 SQL Server 中,没有与 Oracle 聚集相似的结构。

原则上,在表上定义聚集索引可改善 SQL Server 性能和空间管理。如果不了解给定表的查询或更新模式,可在主键上创建聚集索引。

下表给出了,摘自示例应用程序源代码。请注意 SQL Server 聚集索引的使用。

Oracle CREATE TABLE Microsoft SQL Server CREATE TABLE STUDENT_ADMIN.GRADE (

STUDENT_ADMIN.GRADE ( SSN CHAR(9) NOT NULL, SSN CHAR(9) NOT NULL, CCODE VARCHAR(4) NOT NULL, CCODE VARCHAR2(4) NOT NULL, GRADE VARCHAR(2) NULL, GRADE VARCHAR2(2) NULL, CONSTRAINT CONSTRAINT GRADE_SSN_CCODE_PK GRADE_SSN_CCODE_PK PRIMARY KEY (SSN, CCODE) PRIMARY KEY CLUSTERED (SSN, CCODE), CONSTRAINT GRADE_SSN_FK CONSTRAINT GRADE_SSN_FK FOREIGN KEY (SSN) REFERENCES FOREIGN KEY (SSN) REFERENCES STUDENT_ADMIN.STUDENT (SSN), STUDENT_ADMIN.STUDENT (SSN), CONSTRAINT GRADE_CCODE_FK CONSTRAINT GRADE_CCODE_FK FOREIGN KEY (CCODE) REFERENCES FOREIGN KEY (CCODE) REFERENCES DEPT_ADMIN.CLASS (CCODE) DEPT_ADMIN.CLASS (CCODE) ) ) 非聚集索引

在非聚集索引中,索引数据和表数据在物理上是分离的,且表中的行不按照索引的顺序存储。可以把 Oracle 索引定义迁移到 Microsoft SQL Server 非聚集索引定义(如下面例子所示)。但是,出于性能方面的考虑,可能希望选择给定表的一个索引,并把它创建为聚集索引。

Oracle Microsoft SQL Server CREATE INDEX STUDENT_ADMIN.STUDENT_ MAJOR_IDX ON STUDENT_ADMIN.STUDENT CREATE NONCLUSTERED INDEX (MAJOR) STUDENT_MAJOR_IDX TABLESPACE USER_DATA ON USER_DB.STUDENT_ PCTFREE 0 ADMIN.STUDENT (MAJOR) STORAGE (INITIAL 10K NEXT 10K MINEXTENTS 1 MAXEXTENTS UNLIMITED) 索引的语法和命名

在 Oracle 中,索引名在用户帐户中是唯一的。在 Microsoft SQL Server 中,索引名在表名称中必须是唯一的,但在用户帐户或数据库中则不一定是唯一的。因此,在 SQL Server 中创建或删除索引时,必须指明表的名称和索引名称。此外,SQL Server DROP INDEX 语句可以同时删除多个索引。

Oracle CREATE [UNIQUE] INDEX [schema].index_name Microsoft SQL Server CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED] ON [schema.]table_name (column_name [, column_name]...) [INITRANS n] [MAXTRANS n] [TABLESPACE tablespace_name] [STORAGE storage_parameters] [PCTFREE n] [NOSORT] DROP INDEX ABC; INDEX index_name ON table (column [,Un]) [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 树索引结构中级别的数目。使用较高的填充因子值,可更有效地使用索引页空间,访问索引数据需要较少的磁盘 I/O,并减少了 B 树索引结构中级别的数目。

PAD_INDEX 选项指定了,将填充因子应用到索引的决定节点页以及数据页中。

尽管在 Oracle 中,必须调整 PCTFREE 参数来优化性能,但在 CREATE INDEX 语句中,一般不需要加入 FILLFACTOR 选项。填充因子可用于优化性能。仅当使用现有数据在表上创建新索引,并且能够准确预估该数据以后的变化时,填充因子才是有用的。

如果已经把 Oracle 索引的 PCTFREE 设为 0,则考虑使用值为 100 的填充因子。它用于不发生插入和更新的表(只读表)。填充因子设为 100 时,SQL Server 创建每页均百分之百填充的索引。

忽略重复的关键字

对于 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 Books Online。

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)

您可能会发现,使用临时表带来了很多优势,完全有理由为此而修改程序代码。

Microsoft SQL Server 有一些比 Oracle 更为强健的数据类型。Oracle 和 SQL Server 数据类型之间有多种转换方式。建议使用 DTS 向导自动创建新的 CREATE TABLE 语句。必要时,可修改这些语句。

Oracle CHAR VARCHAR2 和 LONG RAW 和 LONG RAW Microsoft SQL Server 建议使用 char。因为 char 类型的列使用固定的存储长度,所以,访问时比 varchar 列要快一些。 varchar 或 text。(如果 Oracle 列中数据值的长度为 8000 字节或更少,则使用 varchar;否则,必须使用 text。) varbinary 或 image。(如果 Oracle 列中数据值的长度为 8000 字节或更少,则使用 varbinary;否则,必须使用 image。) NUMBER DATE ROWID CURRVAL, NEXTVAL SYSDATE USER 如果整数在 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 数据类型。 datetime。 使用 identity 列类型。 使用 identity 列类型以及 @@IDENTITY、IDENT_SEED() 和 IDENT_INCR() 函数。 GETDATE()。 USER。 使用 Unicode 数据

Unicode 规范给世界各地广泛使用的几乎所有字符定义了统一的编码方案。所有计算机使用该 Unicode 规范,将 Unicode 数据中的位模式统一转换为字符。这就保证了在所有的计算机上,相同的位模式总是转换成相同的字符。数据可以从一个数据库或计算机自由地传输到另一个上,而不必担心接收系统不能把位模式正确转换为字符。

对于每个字符使用 1 个字节编码的数据类型来说,一个问题是这种数据类型只能表示 256 个不同的字符。这就要求对于不同的字母表,必须采用多个编码规范(或代码页)。它也不能处理像日语 Kanji 或韩国语 Hangul 字母表这样有几千个字符的系统。

Microsoft SQL Server 使用与 SQL Server 一起安装的代码页中的定义,将 char、varchar 和 text 列中的位模式转换成字符。客户计算机使用与操作系统一起安装的代码页解释位模式。有许多种不同的代码页。有些字符在一些代码页中,但不在其它代码页中。有些字符在一些代码页中用一种位模式定义,在其它代码页中则使用另一种位模式。当创建必须处理各种语言的国际化系统时,要为所有计算机挑选满足多个国家语言要求的代码页,就变得十分困难。而且也很难保证,所有计算机与使用不同代码页的系统交互时,能够进行正确转换。

在 Unicode 规范 中,每个字符使用 2 字节编码,从而解决了这一问题。两字节中有足够多的不同模式 (65,536),可以使单一规范涵盖大多数通用的商务语言。因为所有的 Unicode 系统均使用相同的位模式表示所有字符,当字符从一个系统迁移到另一个系统时,不会出现字符转换错误的问题。

在 SQL Server 中,nchar、nvarchar 和 ntext 数据类型均支持 Unicode 数据。有关 SQL Server 数据类型的详细信息,请参见 SQL Server Books Online。

用户定义的数据类型。

可为 model 数据库或单个用户数据库创建用户定义的数据类型。如果用户定义的数据类型是为 model 定义的,此后创建的所有新用户数据库均可使用该数据类型。用户定义的数据类型是用 sp_addtype 系统存储过程定义的。有关详细信息,请参见 SQL Server Books Online。 可以在 CREATE TABLE 和 ALTER TABLE 语句中使用用户定义的数据类型,并将其与默认值和规则绑定在一起。表创建过程中,如果使用用户定义的数据类型时,明确地定义了为空性,则它优先于数据类型创建时定义的为空性。

此例给出了,如何创建一个用户定义的数据类型。参数为用户类型名称、数据类型和为空性。 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 Books Online。

Microsoft SQL Server 对象的权限可以授予给其它数据库用户、数据库组和 public 角色,也可以被其拒绝或撤销。与 Oracle 不同,SQL Server 不允许对象所有者给对象授予 ALTER TABLE 和 CREATE INDEX 权限。这些权限必须只属于对象所有者。

GRANT 语句在安全系统中创建一个条目,允许当前数据库中的用户处理当前数据库中的数据或执行特定的 Transact-SQL 语句。在 Oracle 和 SQL Server 中,GRANT 语句的语法是相同的。

DENY 语句在安全系统中创建一个条目,拒绝当前数据库中安全帐户的权限,并禁止安全帐户以组或角色成员身份继承权限。Oracle 没有 DENY 语句。REVOKE 语句撤销以前授予当前数据库中一个用户的权限或被其拒绝的权限。

Oracle Microsoft SQL Server GRANT {ALL [PRIVILEGES] | permission[,Un]} { [(column[,Un])] ON {table | view} | ON {table | view}[(column[,Un])] | ON {stored_procedure | extended_procedure} } TO security_account[,Un] [WITH GRANT OPTION] [AS {group | role}] REVOKE [GRANT OPTION FOR] {ALL [PRIVILEGES] | GRANT {ALL permission[,Un]} [PRIVILEGES][column_list] | { permission_list [column_list]} [(column[,Un])] ON {table | view} ON {table_name [(column_list)] | ON {table | view}[(column[,Un])] | view_name [(column_list)] | {stored_procedure | | stored_procedure_name} extended_procedure} TO {PUBLIC | name_list } } [WITH GRANT OPTION] {TO | FROM} security_account[,Un] [CASCADE] [AS {group | role}] DENY {ALL [PRIVILEGES] | permission[,Un]} { [(column[,Un])] ON {table | view} | ON {table | view}[(column[,Un])] | ON {stored_procedure | extended_procedure} } TO security_account[,Un] [CASCADE] 有关对象级权限的详细信息,请参见 SQL Server Books Online。

在 Oracle 中,REFERENCES 权限只能授予一个用户。SQL Server 则允许将 REFERENCES 权限授予数据库用户和数据库组。在 Oracle 和 SQL Server 中,INSERT、UPDATE、DELETE 和 SELECT 权限授予的方式相同。

实施数据完整性和业务规则

实施数据完整性确保了数据库中数据的质量。在表的规划中,有两个重要的步骤,即识别列的有效值,以及确定如何在列中实施数据完整性。数据完整性可以分为四个类别,并用不同的方法来实施。

完整性类型 实体完整性 范围完整性 引用完整性 用户定义的完整性 实施方式 PRIMARY KEY 约束 UNIQUE 约束 IDENTITY 属性 DEFAULT 定义 FOREIGN KEY 约束 CHECK 约束 为空性 范围 DEFAULT 定义 FOREIGN KEY 约束 CHECK 约束 为空性 在 CREATE TABLE 中的列级和表级约束 存储过程 触发器。 实体完整性把一行定义为特定表的一个单独实体。实体完整性通过索引、UNIQUE 约束、PRIMARY KEY 约束或 IDENTITY 属性,来实施表的标识符列或主键的完整性。

约束的命名

应该始终显式命名约束。如果没有,则 Oracle 和 Microsoft SQL Server 使用不同的命名规则隐式命名约束。这些命名上的差别会给迁移过程带来不必要的麻烦。在删除或禁用约束时,就会造成不一致,因为必须使用名称,约束才能被删除。对于 Oracle 和 SQL Server 来说,显式命名约束的语法是相同的。 CONSTRAINT constraint_name

主键和唯一列

SQL-92 标准要求,主键中的所有值应该唯一,并且该列不允许有空值。一旦定义了 PRIMARY KEY 或 UNIQUE 约束,Oracle 和 Microsoft SQL Server 通过自动创建唯一索引,来实施唯一性。此外,主键列自动定义为 NOT NULL。每个表只允许一个主键。

对主键来说,默认地创建一个 SQL Server 聚集索引,尽管也可以请求非聚集索引。主键上的 Oracle 索引可以通过删除或禁用该约束来删除,而 SQL Server 索引只能通过删除该约束来删除。

在两种 RDBMS 中,均可使用 UNIQUE 约束来定义备用键。在任一表上,均可定义多个 UNIQUE 约束。UNIQUE 约束列可为空。在 SQL Server 中,除非另外指定,默认创建非聚集索引。 在迁移应用程序时,要注意,对于完全唯一键(单个或多个列索引),SQL Server 只允许一行包含 NULL 值,而 Oracle 允许任意数量的行包含 NULL 值。

Oracle 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) ) Microsoft SQL Server CREATE TABLE USER_DB.DEPT_ADMIN.DEPT (DEPT VARCHAR(4) NOT NULL, DNAME VARCHAR(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 ONCHECK 选项一起使用,也可实现上述过程。 此插图给出了,这一过程的对比。

在 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 应用程序使用 SEQUENCE,则可以方便地对它进行修改,来使用 Microsoft SQL Server IDENTITY 属性。

类别 语法 Microsoft SQL Server IDENTITY CREATE TABLE new_employees ( Empid int IDENTITY (1,1), Employee_Name varchar(60), CONSTRAINT Emp_PK PRIMARY KEY (Empid) ) 如果增加间隔为 5: CREATE TABLE new_employees ( Empid int IDENTITY (1,5), Employee_Name varchar(60), CONSTRAINT Emp_PK PRIMARY KEY (Empid) ) 每个表中的标识符一个 列 允许空值 否 可否使用默认约束、不能使用 值 实施唯一性 是 在 INSERT、SELECT INTO 或大容量复制语句完成之后,查询@@IDENTITY (function) 当前最大的标识编号 返回在标识符列创建过程中指定的种IDENT_SEED('table_name') 子值 返回在标识符列创建过程中指定的增IDENT_INCR('table_name') 量值 当引用具有 IDENTITY 属性的列时,在 SELECT、SELECT 语法 INSERT、UPDATE 和 DELETE 语句中,可以使用关键字 IDENTITYCOL 代替列的名称。 尽管 IDENTITY 属性在一个表中自动完成行编号,但不同的表(每个表均有其自己的标识符列)的属性值可能会相同。这是因为,IDENTITY 属性只保证在使用它的表中唯一。如果应用程序必须生成一个标识符列,其在整个数据库中、或者甚至每个联网计算机上的每个数据库中都是唯一,则使用 ROWGUIDCOL 属性、uniqueidentifier 数据类型和 NEWID 函数。SQL Server 使用全局唯一标识符列,来合并复制,确保在表的多个副本中,行被唯一地标识。 有关创建和修改标识符列的详细信息,请参见 SQL Server Books Online。

对于给定列,范围完整性实施了有效的条目。范围完整性是通过限制可能值的类型(通过数据类型)、格式(通过 CHECK 约束)或范围(通过 REFERENCE 和 CHECK 约束)实施的。

DEFAULT 和 CHECK 约束

Oracle 把默认值作为列属性,而 Microsoft SQL Server 把默认值作为约束。SQL Server DEFAULT 约束可以包含常量、不带参数的内置函数(niladci 函数)或 NULL。

要方便地迁移 Oracle DEFAULT 列属性,应该在 SQL Server 列级中定义 DEFAULT 约束,而不必使用约束名称。对于每个 DEFAULT 约束,SQL Server 均生成一个唯一的名称。

在 Oracle 和 SQL Server 中,定义 CHECK 约束的语法是相同的。搜索条件必须对一个布尔表达式进行求值,并且不能包括子查询。列级 CHECK 约束只能引用受约束的列,表级 CHECK 约束只可以引用受约束表中的列。可以为一个表定义多个 CHECK 约束。在 CREATE TABLE 语句中,SQL Server 语法规定,在一个列上只允许创建一个列级 CHECK 约束,约束可以有多个条件。 测试修改后的 CREATE TABLE 语句的最好方法是,使用 SQL Server 中的 SQL Server 查询分析器,并分析该语法。结果窗格给出所有的错误。有关约束语法的详细信息,请参见 SQL Server Books Online。

Oracle Microsoft SQL Server CREATE TABLE STUDENT_ADMIN.STUDENT ( CREATE TABLE USER_DB.STUDENT SSN CHAR(9) NOT NULL, _ADMIN.STUDENT ( FNAME VARCHAR2(12) NULL, SSN CHAR(9) NOT NULL, LNAME VARCHAR2(20) NOT NULL, FNAME VARCHAR(12) NULL, GENDER CHAR(1) NOT NULL LNAME VARCHAR(20) NOT NULL, CONSTRAINT GENDER CHAR(1) NOT NULL STUDENT_GENDER_CK CONSTRAINT STUDENT_GENDER_CK CHECK (GENDER IN ('M','F')), CHECK (GENDER IN ('M','F')), MAJOR VARCHAR2(4) MAJOR VARCHAR(4) DEFAULT 'Undc' NOT NULL, DEFAULT 'Undc' NOT NULL, BIRTH_DATE DATE NULL, BIRTH_DATE DATETIME NULL, TUITION_PAID NUMBER(12,2) TUITION_PAID NUMERIC(12,2) NULL, NULL, TUITION_TOTAL NUMERIC(12,2) NULL, TUITION_TOTAL NUMBER(12,2) START_DATE DATETIME NULL, NULL, GRAD_DATE DATETIME NULL, START_DATE DATE NULL, LOAN_AMOUNT NUMERIC(12,2) NULL, GRAD_DATE DATE NULL, DEGREE_PROGRAM CHAR(1) LOAN_AMOUNT NUMBER(12,2) NULL, DEFAULT 'U' NOT NULL DEGREE_PROGRAM CHAR(1) CONSTRAINT STUDENT_DEGREE_CK DEFAULT 'U' NOT NULL CHECK CONSTRAINT (DEGREE_PROGRAM IN ('U', 'M', STUDENT_DEGREE_CK CHECK 'P','D')), (DEGREE_PROGRAM IN ('U', 'M', ... 'P', 'D')), ... 有关用户定义的规则和默认值的说明:出于向后兼容的考虑,仍保留 Microsoft SQL Server 规则和默认值,但对于新的应用程序开发,建议使用 CHECK 和 DEFAULT 约束。有关详细信息,请参见 SQL Server Books Online。

为空性

Microsoft SQL Server 和 Oracle 创建列约束,来实施为空性。Oracle 列默认为 NULL,除非在 CREATE TABLE 或 ALTER TABLE 语句中指定了 NOT NULL。在 Microsoft SQL Server 中,数据库和会话设置可以覆盖列定义中使用的数据类型为空性。

所有的 SQL 脚本(不论是 Oracle 还是 SQL Server)都应该为每一列显式定义 NULL 和 NOT NULL。要了解这一策略是如何实施的,请参见 Oratable.sql 和 Sstable.sql 示例表创建脚本。如果没有显式定义,列的为空性遵循下列规则。

Null 设置 说明 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 ASNI_NULL_DFLT 选项),会话没有改变,并且没有定义 数据库设为默认值(ANSI null default 为 false),那么,SQL Server 赋值为 NOT NULL。 下表提供了一个用于定义引用完整性约束的语法比较。

约束 Microsoft SQL Server [CONSTRAINT [CONSTRAINT constraint_name] constraint_name] PRIMARY KEY [CLUSTERED | PRIMARY KEY (col_name [, NONCLUSTERED] (col_name [, PRIMARY KEY col_name2 [..., col_name2 [..., col_name16]]) col_name16]]) [USING INDEX [ON segment_name] storage_parameters] [NOT FOR REPLICATION] [CONSTRAINT [CONSTRAINT constraint_name] constraint_name] UNIQUE [CLUSTERED | UNIQUE (col_name [, NONCLUSTERED](col_name [, UNIQUE col_name2 [..., col_name2 [..., col_name16]]) col_name16]]) [USING INDEX [ON segment_name] storage_parameters] [NOT FOR REPLICATION] [CONSTRAINT [CONSTRAINT constraint_name] constraint_name] FOREIGN KEY [FOREIGN KEY (col_name [FOREIGN KEY (col_name [, [, col_name2 [..., col_name2 [..., Oracle col_name16]])] REFERENCES [owner.]ref_table [(ref_col [, ref_col2 [..., ref_col16]])] [ON DELETE CASCADE] col_name16]])] DEFAULT CHECK REFERENCES [owner.]ref_table [(ref_col [, ref_col2 [..., ref_col16]])] [NOT FOR REPLICATION] [CONSTRAINT constraint_name] 列属性,但不是约束 DEFAULT DEFAULT {constant_expression | (constant_expression) niladic-function | NULL} [FOR col_name] [NOT FOR REPLICATION] [CONSTRAINT [CONSTRAINT constraint_name] constraint_name] CHECK [NOT FOR REPLICATION] CHECK (expression) (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 Server CREATE PROC[EDURE] procedure_name [;number] [ data_type} [VARYING] [= CREATE OR REPLACE PROCEDURE {@parameter default] [OUTPUT] [user.]procedure ] [(argument [IN | OUT] datatype [,Un] [, argument [IN | OUT] [WITH datatype] { RECOMPILE | ENCRYPTION | {IS | AS} block RECOMPILE, ENCRYPTION} ] [FOR REPLICATION] AS sql_statement [Un] 在 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 Server CREATE OR REPLACE PACKAGE STUDENT_ADMIN.P1 CREATE PROCEDURE AS ROWCOUNT NUMBER :=0; STUDENT_ADMIN.SHOW_ CURSOR C1 RETURN STUDENT%ROWTYPE; RELUCTANT_STUDENTS FUNCTION SHOW_RELUCTANT_STUDENTS AS SELECT FNAME+'' (WORKVAR OUT VARCHAR2) RETURN NUMBER; +LNAME+', social END P1; security number'+ SSN+' / is not enrolled in any classes!' CREATE OR REPLACE PACKAGE BODY FROM STUDENT_ADMIN.P1 AS CURSOR C1 RETURN STUDENT_ADMIN.STUDENT STUDENT%ROWTYPE IS S SELECT * FROM STUDENT_ADMIN.STUDENT WHERE NOT EXISTS WHERE NOT EXISTS (SELECT 'X' FROM (SELECT 'X' FROM STUDENT_ADMIN.GRADE STUDENT_ADMIN.GRADE G WHERE GRADE.SSN=STUDENT.SSN) ORDER BY SSN; WHERE G.SSN=S.SSN) ORDER BY SSN FUNCTION SHOW_RELUCTANT_STUDENTS RETURN@@ROWCOUNT (WORKVAR OUT VARCHAR2) RETURN NUMBER IS GO 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); 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。

本文来源:https://www.bwwdw.com/article/6zew.html

Top