數據類型比較
類型名稱 Oracle SQLServer 比較
字符數據類型 CHAR CHAR 都是固定長度字符資料但oracle里面最大度為2kb,SQLServer里面最大長度為8kb 變長字符數據類型 VARCHAR2 VARCHAR Oracle里面最大長度為4kb,SQLServer里面最大長度為8kb 根據字符集而定的固定長度字符串 NCHAR NCHAR 前者最大長度2kb后者最大長度4kb 根據字符集而定的可變長度字符串 NVARCHAR2 NVARCHAR 二者最大長度都為4kb 日期和時間數據類型 DATE 有Datetime和Smalldatetime兩種 在oracle里面格式為DMY在SQLSerser里面可以調節,默認的為MDY 數字類型 NUMBER(P,S) NUMERIC[P(,S)] Oracle里面p代表小數點左面的位數,s代表小數點右面的位數。而SQLServer里面p代表小數點左右兩面的位數之和,s代表小數點右面的位數。 數字類型 DECIMAL(P,S) DECIMAL[P(,S)] Oracle里面p代表小數點左面的位數,s代表小數點右面的位數。而SQLServer里面p代表小數點左右兩面的位數之和,s代表小數點右面的位數。 整數類型 INTEGER INT 同為整數類型,存儲大小都為4個字節 浮點數類型 FLOAT FLOAT 實數類型 REAL REAL
ORACLE內部函數大全以及與SQLSERVER的區別: 下面是Oracle支持的字符函數和它們的Microsoft SQL Server等價函數。
函數 Oracle Microsoft SQL Server 把字符轉換為ASCII :ASCII ASCII 字串連接: CONCAT --------------(expression + expression) 把ASCII轉換為字符 CHR, CHAR 返回字符串中的開始字符(左起) INSTR ,---------------CHARINDEX 把字符轉換為小寫 LOWER ---------------------LOWER 把字符轉換為大寫 UPPER-------------------- UPPER 填充字符串的左邊 LPAD --------------------N/A 清除開始的空白 LTRIM--------------------LTRIM 清除尾部的空白 RTRIM --------------------RTRIM 字符串中的起始模式(pattern) INSTR --------------------PATINDEX 多次重復字符串 RPAD --------------------REPLICATE 字符串的語音表示 SOUNDEX --------------------SOUNDEX 重復空格的字串 RPAD --------------------SPACE 從數字數據轉換為字符數據 TO_CHAR --------------------STR 子串 SUBSTR --------------------SUBSTRING 替換字符 REPLACE --------------------STUFF 將字串中的每個詞首字母大寫 INITCAP --------------------N/A 翻譯字符串 TRANSLATE --------------------N/A 字符串長度 LENGTH-------------------- DATELENGTH or LEN 列表中最大的字符串 GREATEST-------------------- N/A 列表中最小的字符串 LEAST --------------------N/A 如果為NULL則轉換字串 NVL-------------------- ISNULL
日期函數
下面是Oracle支持的日期函數和它們的Microsoft SQL Server等價函數。
函數 Oracle --------------------Microsoft SQL Server 日期相加 (date column +/- value) or ADD_MONTHS --------------------DATEADD
兩個日期的差 (date column +/- value) or MONTHS_BETWEEN --------------------DATEDIFF 當前日期和時間 SYSDATE --------------------GETDATE() 一個月的最后一天 LAST_DAY --------------------N/A 時區轉換 NEW_TIME --------------------N/A 日期后的第一個周日 NEXT_DAY --------------------N/A 代表日期的字符串 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 16進制轉換為2進制 HEX_TO_RAW --------------------CONVERT 2進制轉換為16進制 RAW_TO_HEX --------------------CONVERT
其它行級別的函數
下面是Oracle支持的其它行級別的函數以及它們的Microsoft SQL Server等價函數。
函數 Oracle --------------------Microsoft SQL Server 返回第一個非空表達式 DECODE -------------------------------------COALESCE 當前序列值 CURRVAL --------------------N/A 下一個序列值 NEXTVAL --------------------N/A
用戶登錄賬號ID數字 UID --------------------SUSER_ID 用戶登錄名 USER --------------------SUSER_NAME 用戶數據庫ID數字 UID --------------------USER_ID 用戶數據庫名 USER --------------------USER_NAME 當前用戶 CURRENT_USER -------------------- CURRENT_USER 用戶環境(audit trail) USERENV --------------------N/A 在CONNECT BY子句中的級別 LEVEL --------------------N/A
合計函數
下面是Oracle支持的合計函數和它們的Microsoft SQL Server等價函數。
函數 Oracle --------------------Microsoft SQL Server Average AVG -------------------- AVG Count COUNT --------------------COUNT Maximum MAX -------------------- MAX Minimum MIN --------------------MIN Standard deviation STDDEV --------------------STDEV or STDEVP Summation SUM -------------------- SUM Variance VARIANCE --------------------VAR or VARP
條件測試
Oracle的DECODE語句和Microsoft SQL Server的CASE表達式都執行條件測試。 當test_value中的值和后面的任何表達式匹配的時候,相關的值就返回。如果沒有找到任何匹配的值,就返回default_value。 如果沒有指定default_value,在沒有匹配的時候,DECODE和CASE都返回一個NULL。下表顯示了該語句的語法, 同時給出了轉換DECODE命令的示例。
Oracle Microsoft SQL DECODE (test_value, expression1, value1 <,expression2, value2] […> [,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
[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聯機手冊。
把值轉換為不同的數據類型
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以及RAWTOTEXT函數相同的功能。
這里所指的數據類型是任何表達式將被轉換成為的系統數據類型。不能使用用戶定義的數據類型。長度參數是可選的, 該參數用於char、varchar、binary以及varbinary數據類型。允許的最大長度是8000。
轉換 Oracle Microsoft SQL Server 字符到數字 TO_NUMBER(?') --------------------CONVERT(numeric, ?') 數字到字符 TO_CHAR(10) --------------------CONVERT(char, 10) 字符到日期 TO_DATE(?-JUL-97') TO_DATE(?-JUL-1997','dd-mon-yyyy')
TO_DATE('July 4, 1997', 'Month dd, yyyy') --------------------CONVERT(datetime, ?-JUL-97')
CONVERT(datetime, ?-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) 16進制到2進制 HEXTORAW(?F')-------------------- CONVERT(binary, ?F') 2進制到16進制 RAWTOHEX(binary_column) --------------------CONVERT(char, binary_column)
請注意字符串是怎樣轉換為日期的。在Oracle中,缺省的日期格式模型是“DD-MON-YY”如果你使用任何其它格式, 你必須提供一個合適的日期格式模型。CONVERT函數自動轉換標准日期格式,不需要任何格式模型。
從日期轉換到字符串時,CONVERT函數的缺省輸出是“dd mon yyyy hh:mm:ss:mmm(24h)”。 用一個數字風格代碼來格式化輸出,使它能輸出為其它類型的日期格式模型。欲了解CONVERT函數的詳細信息,請參閱SQL Server聯機手冊。
下表顯示了Microsoft SQL Server日期的缺省輸出。
Without Century With Century Standard Output - 0 or 100 (*) Default mon dd yyyy hh:miAM (or PM) 1 101 USA mm/dd/yy 2 102 ANSI yy.mm.dd 3 103 British/French dd/mm/yy 4 104 German dd.mm.yy 5 105 Italian dd-mm-yy 6 106 - dd mon yy 7 107 - mon dd, yy 8 108 - hh:mm:ss - 9 or 109 (*) Default milliseconds mon dd yyyy hh:mi:ss:mmm (AM or PM) 10 110 USA mm-dd-yy 11 111 Japan yy/mm/dd 12 112 ISO yymmdd - 13 or 113 (*) Europe default dd mon yyyy hh:mm:ss:mmm(24h) 14 114 - hh:mi:ss:mmm(24h)
用戶定義函數
Oracle PL/SQL函數可以在Oracle SQL語句中使用。在Microsoft SQL Server中一般可以通過其它方式來實現同樣的功能。
在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; No CREATE FUNCTION syntax is required; use CREATE PROCEDURE syntax.
比較操作符
Oracle和Microsoft SQL Server的比較操作符幾乎是一樣的。
算符 Oracle Microsoft SQL Server 等於 (=) (=) 大於 (> (> 小於 (< (< 大於或等於 (>=) (>=) 小於或等於 (<=) (<=) 不等於 (!=, <>, ^=) (!=, <>, ^=) 不大於,不小於 N/A !> , !< 在集合中任意成員中 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 pattern) LIKE LIKE 不像模式(Not like pattern) NOT LIKE NOT LIKE X和y之間的值 BETWEEN x AND y BETWEEN x AND y 不在x和y之間的值 NOT BETWEEN NOT BETWEEN 值存在 EXISTS EXISTS 值不存在 NOT EXISTS NOT EXISTS 值{為|不為}空 IS NULL, IS NOT NULL Same. Also = NULL, != NULL for backward compatibility (not recommended).
模式匹配
SQL Server的LIKE關鍵字提供了有用的通配符搜索功能,這個功能在Oracle中不支持 除了所有的RDBMS都支持的(%)和(_)通配符以外,SQL Server還支持([ ])和([^])通配符。
([ ])字符用來查詢在一個范圍內的所有單個字符。例如,如果你需要查詢包含一個從a到f的字符的數據, 你可以這樣寫:“LIKE '[a-f]'”或者“LIKE '[abcdef]'”。這些附加的通配符的有效性在下表中給出。
Oracle Microsoft SQL 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聯機手冊。
在比較中使用NULL
盡管Microsoft SQL Server傳統上支持SQL-92標准的和一些非標准的NULL行為,但是它還是支持Oracle中的NULL的用法。
為了支持分布式查詢,SET ANSI_NULLS必須設定為ON。
在進行連接的時候,SQL Server的SQL Server ODBC驅動程序和OLE DB提供者自動把SET ANSI_NULLS設定為ON。 這個設置可以在ODBC數據源、ODBC連接屬性、或者是在連接到SQL Server之前在應用程序中設置的OLE DB連接屬性中進行配置。 在從DB-Library應用程序中連接時,SET ANSI_NULLS缺省為OFF。
當SET ANSI_DEFAULTS為ON時,SET ANSI_NULLS被允許。
欲了解關於NULL用法的詳細信息,請參閱SQL Server聯機手冊。
字串連接
Oracle使用兩個管道符號(||)來作為字串連接操作符,SQL Server則使用加號(+)。這個差別要求你在應用程序中做小小的修改。
Oracle Microsoft SQL SELECT FNAME||' '||LNAME AS NAME FROM STUDENT_ADMIN.STUDENT ----------------------------------------------- SELECT FNAME +' '+ LNAME AS NAME FROM STUDENT_ADMIN.STUDENT
流控制(Control-of-Flow)語言
流控制語言控制SQL語句執行流,語句塊以及存儲過程。PL/SQL和Transact-SQL提供了多數相同的結構,但是還是有一些語法差別。
關鍵字
這是兩個RDBMS支持的關鍵字。
語句 Oracle PL/SQL ---------------------Microsoft SQL Server Transact-SQL
聲明變量 DECLARE DECLARE 語句塊 BEGIN...END; BEGIN...END 條件處理 IF…THEN, ELSIF…THEN, ELSE ENDIF; -------------------------------------------------------- IF…[BEGIN…END] ELSE <condition> [BEGIN…END] ELSE IF <condition> CASE expression 無條件結束 RETURN------------ RETURN 無條件結束當前程序塊后面的語句 EXIT BREAK 重新開始一個WHILE循環 N/A CONTINUE 等待指定間隔 N/A (dbms_lock.sleep) WAITFOR 循環控制 WHILE LOOP…END LOOP; ------------ LABEL…GOTO LABEL; FOR…END LOOP; LOOP…END LOOP; WHILE <condition> BEGIN… END LABEL…GOTO LABEL
程序注釋 /* … */, -- /* … */, -- 打印輸出 RDBMS_OUTPUT.PUT_LINE PRINT
引發程序錯誤(Raise program error) RAISE_APPLICATION_ERROR --------------------RAISERROR
執行程序 EXECUTE----------------------EXECUTE 語句終止符 Semicolon ( ------------------N/A
聲明變量
Transact-SQL和PL/SQL的變量是用DECLARE關鍵字創建的。Transact-SQL變量用@標記, 並且就像PL/SQL一樣,在第一次創建時,用空值初始化。
Oracle Microsoft SQL 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變量數據類型定義。一個Transact-SQL變量不能在DECLARE命令中初始化。 在Microsoft SQL Server數據類型定義中也不能使用Oracle的NOT NULL和CONSTANT關鍵字。
像Oracle的LONG和LONG RAW數據類型一樣。文本和圖形數據類型不能被用做變量定義。 此外,Transact-SQL不支持PL/SQL風格的記錄和表的定義。
給變量賦值
Oracle和Microsoft SQL Server提供了下列方法來為本地變量賦值。
Oracle Microsoft SQL Assignment operator (:=) ---------------------SET @local_variable = value SELECT...INTO syntax for selecting column values from a single row ------------------------- SELECT @local_variable = expression [FROM…] for assigning a literal value, an expression involving other local variables, or a column value from a single row
FETCH…INTO syntax------------------------------- FETCH…INTO syntax
這里有一些語法示例
Oracle Microsoft SQL DECLARE VSSN CHAR(9); VFNAME VARCHAR2(12); VLNAME VARCHAR2(20); BEGIN VSSN := ?' SELECT FNAME, LNAME INTO VFNAME, VLNAME FROM STUDENTS WHERE SSN=VSSN; END; ------------------------------------------------------------------------------ DECLARE @VSSN CHAR(9), @VFNAME VARCHAR(12), @VLNAME VARCHAR(20) SET @VSSN = ?' SELECT @VFNAME=FNAME, @VLNAME=LNAME FROM STUDENTS WHERE SSN = @VSSN
語句塊
Oracle PL/SQL和Microsoft SQL Server Transact-SQL都支持用BEGIN…END術語來標記語句塊。 Transact-SQL不需要在DECLARE語句后使用一個語句塊。 --------------------------------------------------------------------------------- -如果在Microsoft SQL Server 中的IF語句和WHILE循環中有多於一個語句被執行,則需要使用BEGIN…END語句塊。
Oracle Microsoft SQL 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中的ELSEIF語句。 可以用嵌套多重IF語句來到達同樣的效果。對於廣泛的條件測試,用CASE表達式也許更容易和可讀一些。
Oracle Microsoft SQL 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循環需要測試一個布爾表達式來決定一個或者多個語句的重復執行。 只要給定的表達式結果為真,這個(些)語句就一直重復執行下去。如果有多個語句需要執行,則這些語句必須放在一個BEGIN…END塊中。
Oracle Microsoft SQL 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 GOTO label; <<label name here>> GOTO label
PRINT語句
Transact-SQL的PRINT語句執行同PL/SQL的RDBMS_OUTPUT.put_line過程同樣的操作。該語句用來打印用戶給定的消息。
用PRINT語句打印的消息上限是8,000個字符。定義為char或者varchar數據類型的變量可以嵌入打印語句。 如果使用其它數據類型的變量,則必須使用CONVERT或者CAST函數。本地變量、全局變量可以被打印。可以用單引號或者雙引號來封閉文本。
從存儲過程返回
Microsoft SQL Server和Oracle都有RETURN語句。RETURN使你的程序從查詢或者過程中無條件的跳出。RETURN是立即的、 完全的、並且可以用於從過程、批處理或者語句塊的任意部分跳出。在REUTRN后面的語句將不會被執行。
Oracle Microsoft SQL RETURN expression: RETURN [integer_expression]
引發程序錯誤(Raising program errors)
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返回不明確的未經處理的異常錯誤消息。 作為代替,當一個不可預見的問題發生的時候,異常處理器總是返回Oracle錯誤消息。
當一個Transact-SQL失敗時,它總是返回一個詳細的錯誤消息給客戶程序。因此,除非需要某些特定的錯誤處理, 一般是不需要RAISERROR語句的。
Oracle Microsoft SQL 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; ------------------------------------------------------ / 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、或者OLEDB程序的游標時,SQL Server 顯式的調用內建的服務器函數來更有效的處理游標。
當從Oracle輸入一個PL/SQL過程時,首先判斷是否需要在Transact-SQL中采用游標來實現同樣的功能。如果游標僅僅返回一 組行給客戶程序,就使用非游標的SELECT語句來返回缺省的結果集合。如果游標用來從行中一次取得一個數據給本地過程變量, 你就必須在Transact-SQL中使用游標。
語法
下表顯示了使用游標的語法。
操作 Oracle Microsoft SQL Server 聲明一個游標 CURSOR cursor_name [(cursor_parameter(s))] IS select_statement; ---------------------------------------------------- DECLARE cursor_name CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | DYNAMIC | FAST_FORWARD] [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] [TYPE_WARNING] FOR select_statement [FOR UPDATE [OF column_name [,…n>] 打開一個游標 OPEN cursor_name [(cursor_parameter(s))]; ---------------- OPEN cursor_name 從游標中提取(Fetching) FETCH cursor_name INTO variable(s) ------------------------------------------------------------------------------------------- FETCH FROM] cursor_name [INTO @variable(s)] 更新提取行 UPDATE table_name SET statement(s)… WHERE CURRENT OF cursor_name; UPDATE table_name SET statement(s)… WHERE CURRENT OF cursor_name 刪除提取行 DELETE FROM table_name WHERE CURRENT OF cursor_name; DELETE FROM table_name WHERE CURRENT OF cursor_name 關閉游標 CLOSE cursor_name; CLOSE cursor_name 清除游標數據結構 N/A DEALLOCATE cursor_name
聲明一個游標
盡管Transact-SQL DECLARE CURSOR語句不支持游標參數的使用,但它確實支持本地變量。當游標打開的時候, 它就使用這些本地變量的值。Microsoft SQL Server在其DECLARE CURSOR中提供了許多附加的功能。
INSENSITIVE選項用來定義一個創建數據的臨時拷貝以被游標使用的游標。游標的所有請求都由這個臨時表來應答。因此 對原表的修改不會反映到那些由fetch返回的用於該游標的數據上。這種類型的游標訪問的數據是不能被修改的。
應用程序可以請求一個游標類型然后執行一個不被所請求的服務器游標類型支持的Transact-SQL語句。SQL Server返回一個錯誤, 指出該游標類型被改變了,或者給出一組參數,隱式的轉換游標。欲取得一個觸發SQL Server 7.0隱式的把游標從一種類型轉換為 另一種類型的參數的完整列表,請參閱SQL Server聯機手冊。
SCROLL選項允許除了前向的抽取以外,向后的、絕對的和相對的數據抽取。一個滾動游標使用一種鍵集合的游標模型,在該模型中, 任何用戶提交的對表的刪除和更新都將影響后來的數據抽取。只有在游標沒有用INSENSITIVE選項聲明時,上面的特性才起作用。
如果選擇了READ ONLY選項,對游標中的行的更新就被禁止。該選項將覆蓋游標的缺省選項棗允許更新。
UPDATE [OF column_list]語句用來在游標中定義一個可更新的列。如果提供了[OF column_list],那么僅僅是那些列出的列可以被修改。 如果沒有指定任何列。則所有的列都是可以更新的,除非游標被定義為READ ONLY。
重要的是,注意到一個SQL Server游標的名字范圍就是連接自己。這和本地變量的名字范圍是不同的。 不能聲明一個與同一個用戶連接上的已有的游標相同名字的游標,除非第一個游標被釋放。
打開一個游標
Transact-SQL不支持向一個打開的游標傳遞參數,這一點和PL/SQL是不一樣的。當一個Transact-SQL游標被打開以后, 結果集的成員和順序就固定下來了。其它用戶提交的對原表的游標的更新和刪除將反映到對所有未加INSENSITIVE選項定義 的游標的數據抽取上。對一個INSENSITIVE游標,將生成一個臨時表。
抽取數據
Oracle游標只能向前移動棗沒有向后或者相對滾動的能力。SQL Server游標可以向前或者向后滾動,具體怎么滾動, 要由下表給出的數據抽取選項來決定。只有在游標是用SCROLL選項聲明的前提下,這些選項才能使用。
卷動選項 描述 NEXT 如果這是對游標的第一次提取,則返回結果集合的第一行;否則,在結果結合內移動游標到下一行。 NEXT是在結果集合中移動的基本方法 。NEXT是缺省的游標提取(fetch)。 PRIOR 返回結果集合的前一行。 FIRST 把游標移動到結果集合的第一行,同時返回第一行。 LAST 把游標移動到結果集合的最后一行,同時返回最后一行。 ABSOLUTE n 返回結果集合的第n行。如果n為負數,則返回倒數第n行 RELATIVE 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的值。只有游標是用SCROLL選項定義的情況下, 才會返回-2值。在每一次數據抽取之后都必須檢查該變量,以確保數據的有效性。
SQL Server不支持Oracle的游標FOR循環語法。
CURRENT OF子句
更新和刪除的CURRENT OF子句語法和函數在PL/SQL和Transact-SQL中是一樣的。在給定游標中,在當前行上執行定位的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 Microsoft SQL ----------------------------------------------------------------------------------------------------------- DECLARE VSSN CHAR(9); VFNAME VARCHAR(12); VLNAME VARCHAR(20); ----------------------------------------------------------------------------------------------------------- DECLARE @VSSN CHAR(9), @VFNAME VARCHAR(12), @VLNAME VARCHAR(20) CURSOR CUR1 IS SELECT SSN, FNAME, LNAME FROM STUDENT ORDER BY LNAME;
BEGIN OPEN CUR1; FETCH CUR1 INTO VSSN, VFNAME, VLNAME; WHILE (CUR1%FOUND) LOOP FETCH CUR1 INTO VSSN, VFNAME, VLNAME; END LOOP; CLOSE CUR1; END; ----------------------------------------------------------------------------------------------------------- DECLARE curl CURSOR FOR SELECT SSN, FNAME, LNAME FROM STUDENT ORDER BY SSN OPEN CUR1 FETCH NEXT FROM CUR1 INTO @VSSN, @VFNAME, @VLNAME WHILE (@@FETCH_STATUS <> -1) BEGIN FETCH NEXT FROM CUR1 INTO @VSSN, @VFNAME, @VLNAME END CLOSE CUR1 DEALLOCATE CUR1
類型名稱 Oracle SQLServer 比較
字符數據類型 CHAR CHAR 都是固定長度字符資料但oracle里面最大度為2kb,SQLServer里面最大長度為8kb 變長字符數據類型 VARCHAR2 VARCHAR Oracle里面最大長度為4kb,SQLServer里面最大長度為8kb 根據字符集而定的固定長度字符串 NCHAR NCHAR 前者最大長度2kb后者最大長度4kb 根據字符集而定的可變長度字符串 NVARCHAR2 NVARCHAR 二者最大長度都為4kb 日期和時間數據類型 DATE 有Datetime和Smalldatetime兩種 在oracle里面格式為DMY在SQLSerser里面可以調節,默認的為MDY 數字類型 NUMBER(P,S) NUMERIC[P(,S)] Oracle里面p代表小數點左面的位數,s代表小數點右面的位數。而SQLServer里面p代表小數點左右兩面的位數之和,s代表小數點右面的位數。 數字類型 DECIMAL(P,S) DECIMAL[P(,S)] Oracle里面p代表小數點左面的位數,s代表小數點右面的位數。而SQLServer里面p代表小數點左右兩面的位數之和,s代表小數點右面的位數。 整數類型 INTEGER INT 同為整數類型,存儲大小都為4個字節 浮點數類型 FLOAT FLOAT 實數類型 REAL REAL
ORACLE內部函數大全以及與SQLSERVER的區別: 下面是Oracle支持的字符函數和它們的Microsoft SQL Server等價函數。
函數 Oracle Microsoft SQL Server 把字符轉換為ASCII :ASCII ASCII 字串連接: CONCAT --------------(expression + expression) 把ASCII轉換為字符 CHR, CHAR 返回字符串中的開始字符(左起) INSTR ,---------------CHARINDEX 把字符轉換為小寫 LOWER ---------------------LOWER 把字符轉換為大寫 UPPER-------------------- UPPER 填充字符串的左邊 LPAD --------------------N/A 清除開始的空白 LTRIM--------------------LTRIM 清除尾部的空白 RTRIM --------------------RTRIM 字符串中的起始模式(pattern) INSTR --------------------PATINDEX 多次重復字符串 RPAD --------------------REPLICATE 字符串的語音表示 SOUNDEX --------------------SOUNDEX 重復空格的字串 RPAD --------------------SPACE 從數字數據轉換為字符數據 TO_CHAR --------------------STR 子串 SUBSTR --------------------SUBSTRING 替換字符 REPLACE --------------------STUFF 將字串中的每個詞首字母大寫 INITCAP --------------------N/A 翻譯字符串 TRANSLATE --------------------N/A 字符串長度 LENGTH-------------------- DATELENGTH or LEN 列表中最大的字符串 GREATEST-------------------- N/A 列表中最小的字符串 LEAST --------------------N/A 如果為NULL則轉換字串 NVL-------------------- ISNULL
日期函數
下面是Oracle支持的日期函數和它們的Microsoft SQL Server等價函數。
函數 Oracle --------------------Microsoft SQL Server 日期相加 (date column +/- value) or ADD_MONTHS --------------------DATEADD
兩個日期的差 (date column +/- value) or MONTHS_BETWEEN --------------------DATEDIFF 當前日期和時間 SYSDATE --------------------GETDATE() 一個月的最后一天 LAST_DAY --------------------N/A 時區轉換 NEW_TIME --------------------N/A 日期后的第一個周日 NEXT_DAY --------------------N/A 代表日期的字符串 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 16進制轉換為2進制 HEX_TO_RAW --------------------CONVERT 2進制轉換為16進制 RAW_TO_HEX --------------------CONVERT
其它行級別的函數
下面是Oracle支持的其它行級別的函數以及它們的Microsoft SQL Server等價函數。
函數 Oracle --------------------Microsoft SQL Server 返回第一個非空表達式 DECODE -------------------------------------COALESCE 當前序列值 CURRVAL --------------------N/A 下一個序列值 NEXTVAL --------------------N/A
用戶登錄賬號ID數字 UID --------------------SUSER_ID 用戶登錄名 USER --------------------SUSER_NAME 用戶數據庫ID數字 UID --------------------USER_ID 用戶數據庫名 USER --------------------USER_NAME 當前用戶 CURRENT_USER -------------------- CURRENT_USER 用戶環境(audit trail) USERENV --------------------N/A 在CONNECT BY子句中的級別 LEVEL --------------------N/A
合計函數
下面是Oracle支持的合計函數和它們的Microsoft SQL Server等價函數。
函數 Oracle --------------------Microsoft SQL Server Average AVG -------------------- AVG Count COUNT --------------------COUNT Maximum MAX -------------------- MAX Minimum MIN --------------------MIN Standard deviation STDDEV --------------------STDEV or STDEVP Summation SUM -------------------- SUM Variance VARIANCE --------------------VAR or VARP
條件測試
Oracle的DECODE語句和Microsoft SQL Server的CASE表達式都執行條件測試。 當test_value中的值和后面的任何表達式匹配的時候,相關的值就返回。如果沒有找到任何匹配的值,就返回default_value。 如果沒有指定default_value,在沒有匹配的時候,DECODE和CASE都返回一個NULL。下表顯示了該語句的語法, 同時給出了轉換DECODE命令的示例。
Oracle Microsoft SQL DECODE (test_value, expression1, value1 <,expression2, value2] […> [,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
[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聯機手冊。
把值轉換為不同的數據類型
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以及RAWTOTEXT函數相同的功能。
這里所指的數據類型是任何表達式將被轉換成為的系統數據類型。不能使用用戶定義的數據類型。長度參數是可選的, 該參數用於char、varchar、binary以及varbinary數據類型。允許的最大長度是8000。
轉換 Oracle Microsoft SQL Server 字符到數字 TO_NUMBER(?') --------------------CONVERT(numeric, ?') 數字到字符 TO_CHAR(10) --------------------CONVERT(char, 10) 字符到日期 TO_DATE(?-JUL-97') TO_DATE(?-JUL-1997','dd-mon-yyyy')
TO_DATE('July 4, 1997', 'Month dd, yyyy') --------------------CONVERT(datetime, ?-JUL-97')
CONVERT(datetime, ?-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) 16進制到2進制 HEXTORAW(?F')-------------------- CONVERT(binary, ?F') 2進制到16進制 RAWTOHEX(binary_column) --------------------CONVERT(char, binary_column)
請注意字符串是怎樣轉換為日期的。在Oracle中,缺省的日期格式模型是“DD-MON-YY”如果你使用任何其它格式, 你必須提供一個合適的日期格式模型。CONVERT函數自動轉換標准日期格式,不需要任何格式模型。
從日期轉換到字符串時,CONVERT函數的缺省輸出是“dd mon yyyy hh:mm:ss:mmm(24h)”。 用一個數字風格代碼來格式化輸出,使它能輸出為其它類型的日期格式模型。欲了解CONVERT函數的詳細信息,請參閱SQL Server聯機手冊。
下表顯示了Microsoft SQL Server日期的缺省輸出。
Without Century With Century Standard Output - 0 or 100 (*) Default mon dd yyyy hh:miAM (or PM) 1 101 USA mm/dd/yy 2 102 ANSI yy.mm.dd 3 103 British/French dd/mm/yy 4 104 German dd.mm.yy 5 105 Italian dd-mm-yy 6 106 - dd mon yy 7 107 - mon dd, yy 8 108 - hh:mm:ss - 9 or 109 (*) Default milliseconds mon dd yyyy hh:mi:ss:mmm (AM or PM) 10 110 USA mm-dd-yy 11 111 Japan yy/mm/dd 12 112 ISO yymmdd - 13 or 113 (*) Europe default dd mon yyyy hh:mm:ss:mmm(24h) 14 114 - hh:mi:ss:mmm(24h)
用戶定義函數
Oracle PL/SQL函數可以在Oracle SQL語句中使用。在Microsoft SQL Server中一般可以通過其它方式來實現同樣的功能。
在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; No CREATE FUNCTION syntax is required; use CREATE PROCEDURE syntax.
比較操作符
Oracle和Microsoft SQL Server的比較操作符幾乎是一樣的。
算符 Oracle Microsoft SQL Server 等於 (=) (=) 大於 (> (> 小於 (< (< 大於或等於 (>=) (>=) 小於或等於 (<=) (<=) 不等於 (!=, <>, ^=) (!=, <>, ^=) 不大於,不小於 N/A !> , !< 在集合中任意成員中 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 pattern) LIKE LIKE 不像模式(Not like pattern) NOT LIKE NOT LIKE X和y之間的值 BETWEEN x AND y BETWEEN x AND y 不在x和y之間的值 NOT BETWEEN NOT BETWEEN 值存在 EXISTS EXISTS 值不存在 NOT EXISTS NOT EXISTS 值{為|不為}空 IS NULL, IS NOT NULL Same. Also = NULL, != NULL for backward compatibility (not recommended).
模式匹配
SQL Server的LIKE關鍵字提供了有用的通配符搜索功能,這個功能在Oracle中不支持 除了所有的RDBMS都支持的(%)和(_)通配符以外,SQL Server還支持([ ])和([^])通配符。
([ ])字符用來查詢在一個范圍內的所有單個字符。例如,如果你需要查詢包含一個從a到f的字符的數據, 你可以這樣寫:“LIKE '[a-f]'”或者“LIKE '[abcdef]'”。這些附加的通配符的有效性在下表中給出。
Oracle Microsoft SQL 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聯機手冊。
在比較中使用NULL
盡管Microsoft SQL Server傳統上支持SQL-92標准的和一些非標准的NULL行為,但是它還是支持Oracle中的NULL的用法。
為了支持分布式查詢,SET ANSI_NULLS必須設定為ON。
在進行連接的時候,SQL Server的SQL Server ODBC驅動程序和OLE DB提供者自動把SET ANSI_NULLS設定為ON。 這個設置可以在ODBC數據源、ODBC連接屬性、或者是在連接到SQL Server之前在應用程序中設置的OLE DB連接屬性中進行配置。 在從DB-Library應用程序中連接時,SET ANSI_NULLS缺省為OFF。
當SET ANSI_DEFAULTS為ON時,SET ANSI_NULLS被允許。
欲了解關於NULL用法的詳細信息,請參閱SQL Server聯機手冊。
字串連接
Oracle使用兩個管道符號(||)來作為字串連接操作符,SQL Server則使用加號(+)。這個差別要求你在應用程序中做小小的修改。
Oracle Microsoft SQL SELECT FNAME||' '||LNAME AS NAME FROM STUDENT_ADMIN.STUDENT ----------------------------------------------- SELECT FNAME +' '+ LNAME AS NAME FROM STUDENT_ADMIN.STUDENT
流控制(Control-of-Flow)語言
流控制語言控制SQL語句執行流,語句塊以及存儲過程。PL/SQL和Transact-SQL提供了多數相同的結構,但是還是有一些語法差別。
關鍵字
這是兩個RDBMS支持的關鍵字。
語句 Oracle PL/SQL ---------------------Microsoft SQL Server Transact-SQL
聲明變量 DECLARE DECLARE 語句塊 BEGIN...END; BEGIN...END 條件處理 IF…THEN, ELSIF…THEN, ELSE ENDIF; -------------------------------------------------------- IF…[BEGIN…END] ELSE <condition> [BEGIN…END] ELSE IF <condition> CASE expression 無條件結束 RETURN------------ RETURN 無條件結束當前程序塊后面的語句 EXIT BREAK 重新開始一個WHILE循環 N/A CONTINUE 等待指定間隔 N/A (dbms_lock.sleep) WAITFOR 循環控制 WHILE LOOP…END LOOP; ------------ LABEL…GOTO LABEL; FOR…END LOOP; LOOP…END LOOP; WHILE <condition> BEGIN… END LABEL…GOTO LABEL
程序注釋 /* … */, -- /* … */, -- 打印輸出 RDBMS_OUTPUT.PUT_LINE PRINT
引發程序錯誤(Raise program error) RAISE_APPLICATION_ERROR --------------------RAISERROR
執行程序 EXECUTE----------------------EXECUTE 語句終止符 Semicolon ( ------------------N/A
聲明變量
Transact-SQL和PL/SQL的變量是用DECLARE關鍵字創建的。Transact-SQL變量用@標記, 並且就像PL/SQL一樣,在第一次創建時,用空值初始化。
Oracle Microsoft SQL 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變量數據類型定義。一個Transact-SQL變量不能在DECLARE命令中初始化。 在Microsoft SQL Server數據類型定義中也不能使用Oracle的NOT NULL和CONSTANT關鍵字。
像Oracle的LONG和LONG RAW數據類型一樣。文本和圖形數據類型不能被用做變量定義。 此外,Transact-SQL不支持PL/SQL風格的記錄和表的定義。
給變量賦值
Oracle和Microsoft SQL Server提供了下列方法來為本地變量賦值。
Oracle Microsoft SQL Assignment operator (:=) ---------------------SET @local_variable = value SELECT...INTO syntax for selecting column values from a single row ------------------------- SELECT @local_variable = expression [FROM…] for assigning a literal value, an expression involving other local variables, or a column value from a single row
FETCH…INTO syntax------------------------------- FETCH…INTO syntax
這里有一些語法示例
Oracle Microsoft SQL DECLARE VSSN CHAR(9); VFNAME VARCHAR2(12); VLNAME VARCHAR2(20); BEGIN VSSN := ?' SELECT FNAME, LNAME INTO VFNAME, VLNAME FROM STUDENTS WHERE SSN=VSSN; END; ------------------------------------------------------------------------------ DECLARE @VSSN CHAR(9), @VFNAME VARCHAR(12), @VLNAME VARCHAR(20) SET @VSSN = ?' SELECT @VFNAME=FNAME, @VLNAME=LNAME FROM STUDENTS WHERE SSN = @VSSN
語句塊
Oracle PL/SQL和Microsoft SQL Server Transact-SQL都支持用BEGIN…END術語來標記語句塊。 Transact-SQL不需要在DECLARE語句后使用一個語句塊。 --------------------------------------------------------------------------------- -如果在Microsoft SQL Server 中的IF語句和WHILE循環中有多於一個語句被執行,則需要使用BEGIN…END語句塊。
Oracle Microsoft SQL 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中的ELSEIF語句。 可以用嵌套多重IF語句來到達同樣的效果。對於廣泛的條件測試,用CASE表達式也許更容易和可讀一些。
Oracle Microsoft SQL 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循環需要測試一個布爾表達式來決定一個或者多個語句的重復執行。 只要給定的表達式結果為真,這個(些)語句就一直重復執行下去。如果有多個語句需要執行,則這些語句必須放在一個BEGIN…END塊中。
Oracle Microsoft SQL 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 GOTO label; <<label name here>> GOTO label
PRINT語句
Transact-SQL的PRINT語句執行同PL/SQL的RDBMS_OUTPUT.put_line過程同樣的操作。該語句用來打印用戶給定的消息。
用PRINT語句打印的消息上限是8,000個字符。定義為char或者varchar數據類型的變量可以嵌入打印語句。 如果使用其它數據類型的變量,則必須使用CONVERT或者CAST函數。本地變量、全局變量可以被打印。可以用單引號或者雙引號來封閉文本。
從存儲過程返回
Microsoft SQL Server和Oracle都有RETURN語句。RETURN使你的程序從查詢或者過程中無條件的跳出。RETURN是立即的、 完全的、並且可以用於從過程、批處理或者語句塊的任意部分跳出。在REUTRN后面的語句將不會被執行。
Oracle Microsoft SQL RETURN expression: RETURN [integer_expression]
引發程序錯誤(Raising program errors)
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返回不明確的未經處理的異常錯誤消息。 作為代替,當一個不可預見的問題發生的時候,異常處理器總是返回Oracle錯誤消息。
當一個Transact-SQL失敗時,它總是返回一個詳細的錯誤消息給客戶程序。因此,除非需要某些特定的錯誤處理, 一般是不需要RAISERROR語句的。
Oracle Microsoft SQL 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; ------------------------------------------------------ / 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、或者OLEDB程序的游標時,SQL Server 顯式的調用內建的服務器函數來更有效的處理游標。
當從Oracle輸入一個PL/SQL過程時,首先判斷是否需要在Transact-SQL中采用游標來實現同樣的功能。如果游標僅僅返回一 組行給客戶程序,就使用非游標的SELECT語句來返回缺省的結果集合。如果游標用來從行中一次取得一個數據給本地過程變量, 你就必須在Transact-SQL中使用游標。
語法
下表顯示了使用游標的語法。
操作 Oracle Microsoft SQL Server 聲明一個游標 CURSOR cursor_name [(cursor_parameter(s))] IS select_statement; ---------------------------------------------------- DECLARE cursor_name CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | DYNAMIC | FAST_FORWARD] [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] [TYPE_WARNING] FOR select_statement [FOR UPDATE [OF column_name [,…n>] 打開一個游標 OPEN cursor_name [(cursor_parameter(s))]; ---------------- OPEN cursor_name 從游標中提取(Fetching) FETCH cursor_name INTO variable(s) ------------------------------------------------------------------------------------------- FETCH FROM] cursor_name [INTO @variable(s)] 更新提取行 UPDATE table_name SET statement(s)… WHERE CURRENT OF cursor_name; UPDATE table_name SET statement(s)… WHERE CURRENT OF cursor_name 刪除提取行 DELETE FROM table_name WHERE CURRENT OF cursor_name; DELETE FROM table_name WHERE CURRENT OF cursor_name 關閉游標 CLOSE cursor_name; CLOSE cursor_name 清除游標數據結構 N/A DEALLOCATE cursor_name
聲明一個游標
盡管Transact-SQL DECLARE CURSOR語句不支持游標參數的使用,但它確實支持本地變量。當游標打開的時候, 它就使用這些本地變量的值。Microsoft SQL Server在其DECLARE CURSOR中提供了許多附加的功能。
INSENSITIVE選項用來定義一個創建數據的臨時拷貝以被游標使用的游標。游標的所有請求都由這個臨時表來應答。因此 對原表的修改不會反映到那些由fetch返回的用於該游標的數據上。這種類型的游標訪問的數據是不能被修改的。
應用程序可以請求一個游標類型然后執行一個不被所請求的服務器游標類型支持的Transact-SQL語句。SQL Server返回一個錯誤, 指出該游標類型被改變了,或者給出一組參數,隱式的轉換游標。欲取得一個觸發SQL Server 7.0隱式的把游標從一種類型轉換為 另一種類型的參數的完整列表,請參閱SQL Server聯機手冊。
SCROLL選項允許除了前向的抽取以外,向后的、絕對的和相對的數據抽取。一個滾動游標使用一種鍵集合的游標模型,在該模型中, 任何用戶提交的對表的刪除和更新都將影響后來的數據抽取。只有在游標沒有用INSENSITIVE選項聲明時,上面的特性才起作用。
如果選擇了READ ONLY選項,對游標中的行的更新就被禁止。該選項將覆蓋游標的缺省選項棗允許更新。
UPDATE [OF column_list]語句用來在游標中定義一個可更新的列。如果提供了[OF column_list],那么僅僅是那些列出的列可以被修改。 如果沒有指定任何列。則所有的列都是可以更新的,除非游標被定義為READ ONLY。
重要的是,注意到一個SQL Server游標的名字范圍就是連接自己。這和本地變量的名字范圍是不同的。 不能聲明一個與同一個用戶連接上的已有的游標相同名字的游標,除非第一個游標被釋放。
打開一個游標
Transact-SQL不支持向一個打開的游標傳遞參數,這一點和PL/SQL是不一樣的。當一個Transact-SQL游標被打開以后, 結果集的成員和順序就固定下來了。其它用戶提交的對原表的游標的更新和刪除將反映到對所有未加INSENSITIVE選項定義 的游標的數據抽取上。對一個INSENSITIVE游標,將生成一個臨時表。
抽取數據
Oracle游標只能向前移動棗沒有向后或者相對滾動的能力。SQL Server游標可以向前或者向后滾動,具體怎么滾動, 要由下表給出的數據抽取選項來決定。只有在游標是用SCROLL選項聲明的前提下,這些選項才能使用。
卷動選項 描述 NEXT 如果這是對游標的第一次提取,則返回結果集合的第一行;否則,在結果結合內移動游標到下一行。 NEXT是在結果集合中移動的基本方法 。NEXT是缺省的游標提取(fetch)。 PRIOR 返回結果集合的前一行。 FIRST 把游標移動到結果集合的第一行,同時返回第一行。 LAST 把游標移動到結果集合的最后一行,同時返回最后一行。 ABSOLUTE n 返回結果集合的第n行。如果n為負數,則返回倒數第n行 RELATIVE 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的值。只有游標是用SCROLL選項定義的情況下, 才會返回-2值。在每一次數據抽取之后都必須檢查該變量,以確保數據的有效性。
SQL Server不支持Oracle的游標FOR循環語法。
CURRENT OF子句
更新和刪除的CURRENT OF子句語法和函數在PL/SQL和Transact-SQL中是一樣的。在給定游標中,在當前行上執行定位的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 Microsoft SQL ----------------------------------------------------------------------------------------------------------- DECLARE VSSN CHAR(9); VFNAME VARCHAR(12); VLNAME VARCHAR(20); ----------------------------------------------------------------------------------------------------------- DECLARE @VSSN CHAR(9), @VFNAME VARCHAR(12), @VLNAME VARCHAR(20) CURSOR CUR1 IS SELECT SSN, FNAME, LNAME FROM STUDENT ORDER BY LNAME;
BEGIN OPEN CUR1; FETCH CUR1 INTO VSSN, VFNAME, VLNAME; WHILE (CUR1%FOUND) LOOP FETCH CUR1 INTO VSSN, VFNAME, VLNAME; END LOOP; CLOSE CUR1; END; ----------------------------------------------------------------------------------------------------------- DECLARE curl CURSOR FOR SELECT SSN, FNAME, LNAME FROM STUDENT ORDER BY SSN OPEN CUR1 FETCH NEXT FROM CUR1 INTO @VSSN, @VFNAME, @VLNAME WHILE (@@FETCH_STATUS <> -1) BEGIN FETCH NEXT FROM CUR1 INTO @VSSN, @VFNAME, @VLNAME END CLOSE CUR1 DEALLOCATE CUR1