盡管Sybase和SQL Server之間的一些差別是相當大的,例如Sybase數據庫管理系統中的存儲過程在SQL Server就不能被編譯,而其它差別則不太大。在完成這一轉換前,對腳本文件和存儲過程中編程邏輯的行為和結果進行測試是很有必要的。
在下面的部分中,我們將討論這二種數據庫系統之間的一些主要的不同點,在移植的規劃階段,我們必須仔細研究這些區別。
數據兼容模式
對SQL Server 2000和Sybase之間的一些兼容性差別的一個臨時性解決方案是改變SQL Server中的數據庫兼容性級別,使之與Sybase相符。為此,我們可以使用sp_dbcmptlevel存儲過程。
下面表中的語句和結果顯示出不同版本數據庫之間的差別:
注意:
1.當兼容性模式被設置為70時,下面的詞匯不能被用作對象名和標識符:BACKUP、DENY、PRECENT、RESTORE和TOP;
2.當兼容性模式被設置為65時,下面的詞匯不能被用作對象名和標識符:AUTHORIZATION、CASCASE、CROSS、DISTRIBUTED、ESCAPE、FULL、INNER、JOIN、LEFT、OUTER、PRIVILEGES、RESTRICT、RIGHT、SCHEMA和WORK。
下面是sp_dbcmptlevel的語法:
sp_dbcmptlevel [[@dbname=] name][,[@new_cmptlevel=]version]
@dbname是用於檢查和改變兼容性水平的數據庫名字;
@new_cmptlevel決定數據庫被設置的兼容性水平(將它設置為70、65、60,缺省值為NULL)。
例如:
sp_dbcmptlevel pubs
這一行代碼返回下面的結果:
The current compatibility level is 70.(當前的兼容性級別為70)
現在我們來看一下另外一個例子:
sp_dbcmptlevel pubs, 65
它返回如下的結果:
DBCC execution completed. (DBCC執行結束)
果DBCC打印出錯誤信息,則需要與系統管理員聯系。我們可以使用rerunsp_dbcmptlevel驗證pubs數據庫是否修改得正確:
sp_dbcmptlevel pubs
它返回下面的結果:
The current compatibility level is 65(當前的兼容性級別為65)
除了上面的例子外,兼容性級別的差別還擴展到了保留字。Sybase和SQL Server都有許多不能被用作數據庫中對象名字的的保留字,二種產品的保留字相似,但並不完全相同。
由於能夠在Sybase中使用的對象可能不能在SQL Server中使用,這一問題使得由Sybase向SQL Server的移植憑添了許多困難。下面是在SQL Server中是保留字,而在Sybase中不是保留字的詞匯清單。
注意:名字為下列清單中詞匯的Sybase數據庫中的對象在移植到SQL Server數據庫時必須換為其它名字。
BACKUP COLUMN COMMITTED CONTAINS CONTAINSTABLE
CROSS CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER
DENY DISTRIBUTED FILE FLOPPY FREETEXT
FREETEXTTABLE FULL IDENTITYCOL INNER JOIN
事務管理模式
Sybase SQL Server Set chained [ on : off ] Set implicit_transactions [on : off ]
在Sybase中使用下面的代碼判斷事務模式:
SELECT @@tranchained GO
下面是可能返回的結果:
0 表明使用的是非鏈鎖式事務模式
1 表明連接運行在鏈鎖模式下
在SQL Server中使用下面的代碼判斷事務模式:
IF (@@options & 2) > 0 PRINT on ELSE PRINT off
下面是可能的返回結果:
0 off >0 on
隔離水平
在一個關系數據庫這樣的多線程應用軟件中,數據庫引擎對運行的進程間的數據是如何被隔離的管理是非常重要的,在表示隔離水平時,Sybase和SQL Server的語法是不同的。下面的表格表明了Sybase和SQL Server在表示隔離水平時的差別。
Sybase SQL Server 0 READ UNCOMMITTED 1 READ COMMITTED 2 REPEATABLE READ 3 SERIALIZABLE
游標語法
二種產品中存儲過程的創建和執行基本相似,但在移植時,游標語句中的一些例外是我們應當注意的。下面是一個例子:
CREATE PROCEDURE sql_cursor AS DECLARE @lname char(20), @fname char(20) DECLARE mycursor CURSOR FOR SELECT au_lname, au_fname FROM authors OPEN mycursor FETCH FROM mycursor INTO @lname, @fname WHILE @@ FETCH_STATUS = 0 /* Sybase數據庫使用@SQLSTATUS而不是@@ FETCH_STATUS */ BEGIN FETCH FROM mycursor INTO @lname, @fname /* ** 這裡應當是一些業務邏輯 */ END CLOSE mycursor DEALLOCATE /* Sybase數據庫在這裡需要CURSOR這個詞 * / mycursor Sybase SQL Server Fetch命令執行成功 0 0 Fetch命令執行失敗 1 -2 沒有可存取的記錄了 2 -1
退回觸發器
SQL Server中不存在這個命令,因此在向SQL Server移植時,使用了ROLLBACK TRIGGER命令的Sybase存儲過程必須被進行修改。在修改帶有觸發器的數據庫表中的數據時,使用ROLLBACK TRIGGER命令容易引起誤解,一個ROLLBACK TRIGGER命令只退回觸發器以及觸發觸發器的數據修改,如果已經被提交了,則事務的其它部分會繼續,被寫到數據庫中。因此,事務中的所有語句可能沒有被成功地完成,但數據已經被提交了。
下面是Sybase數據庫中一個使用ROLLBACK TRIGGER的樣例觸發器:
CREATE TABLE table1 (a int, b int) GO CREATE TRIGGER trigger1 on table1 FOR INSERT AS IF EXISTS (SELECT 1 FROM inserted WHERE a = 100) BEGIN ROLLBACK TRIGGER with RAISERROR 50000 Invalid value for column a END INSERT INTO table2 SELECT a, GETDATE() from inserted RETURN GO
在上面的代碼中,除非a = 100,則所有插入table1的數據也被作為審計行插入table2中,如果a = 100,ROLLBACK TRIGGER命令被觸發,而INSERT命令沒有被觸發,批命令的其它部分繼續執行,這時會出現錯誤信息,表明在一個INSERT命令中出現了錯誤。下面是所有的INSERT命令:
BEGIN TRAN INSERT INTO table1 valueS (1, 1) INSERT INTO table1 valueS (100,2) INSERT INTO table1 valueS (3, 3) GO SELECT * FROM table1
在執行這些命令後,table1和table2二個數據庫表將各有2個記錄,Table1表中的值為1,1以及3,3,由於ROLLBACK TRIGGER命令,第二個INSERT命令沒有執行;Table2表中的值為1,(當前日期)以及3,(當前日期),由於當a = 100時ROLLBACK TRIGGER被觸發,觸發器中的所有處理被中止,100沒有被插入到Table2表中。
在SQL Server中模擬這一操作需要更多的代碼,外部的事務必須與保存點同時使用,如下所示:
CREATE trigger1 on table1 FOR INSERT AS SAVE TRAN trigger1 IF EXISTS (SELECT * FROM inserted WHERE a = 100) BEGIN ROLLBACK TRAN trigger1 RAISERROR 50000 ROLLBACK END INSERT INTO table2 SELECT a, GETDATE() FROM inserted GO
這一觸發器以一個存儲點開始,ROLLBACK TRANSACTION只退回觸發邏輯,而不是整個事務(規模要小於Sybases數據庫中的ROLLBACK TRIGGER語句。對批命令的修改如下:
BEGIN TRAN SAVE TRAN save1 INSERT INTO table1 valueS (1, 1) IF @@error = 50000 ROLLBACK TRAN save1 SAVE TRAN save2 INSERT INTO table1 valueS (100, 1) IF @@error = 50000 ROLLBACK TRAN save2 SAVE TRAN save3 INSERT INTO table1 valueS (3, 3) IF @@error = 50000 ROLLBACK TRAN save3 COMMIT TRAN
我們可以發現,改變不可謂不大。由於ROLLBACK TRIGGER命令能夠使任何批命令不能成功執行,因此在移植的SQL Server存儲過程代碼中必須包括另外的邏輯,根據ROLLBACK TRIGGER的使用,這可能是一個艱巨而必要的任務,沒有什麼捷徑可走。如果在移植後所有的ROLLBACK TRIGGER命令被改變為ROLLBACK TRANSACTION,觸發器的執行也會發生變化,因此我們應當十分小心。