我最近參與了將一個Sybase數據庫移植到Microsoft SQL Server 2000上的項目,我在這一項目上獲得的經驗,將對Sybase數據庫管理員把Sybase數據庫移植到SQL Server 2000平臺上有一定的幫助。
Sybase數據庫與SQL Server2000二者之間的一些差別是相當大的,例如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,觸發器的執行也會發生變化,因此我們應當十分小心。
命令優化
SQL Server能夠對SELECT、INSERT、UPDATE和DELETE命令進行優化,Sybase數據庫則只支持對SELECT命令進行優化。下面是SQL Server和Sybase在GUI方面的對比:
Sybase SQL Server
使用被稱作SHOWPLAN的基于文本的查詢分析工具 使用Query Analyzer。
在ISQL中啟動SHOWPLAN的命令按鈕 多Query Analyzer中啟動SHOWPLAN_ALL或 SHOWPLAN_TEXT的命令
SET SHOWPLAN ON SET SHOWPLAN_ALL
GO GO
臨時數據庫表的名字
表名字的類型 最大長度
SQL Server表名字 128
SQL Server臨時表名字 116
Sybase表名字 30
Sybase臨時表名字 13
數據類型
數據類型 Sybase SQL Server
char(n) 255 8000
varchar(n) 255 8000
nchar(n) 255 4000
nvarchar(n) 255 4000
binary 255 8000
varbinary 255 8000
注意:
1)SQL Server中的bit類型數據的值可以被設置為0、1或NULL。
2) Sybase中的bit類型數據的值不可以被設置為NULL。
同一性列
Sybase SQL Server
Numeric(x,0) Tinyint,smallint,int,decimal(x,0) or numeric(x,0)
打印語法
在進行移植時,所有使用替換語法的打印語句必須被改變為RAISERROR語句。
結論
將Sybase數據庫轉換為SQL Server數據庫并非是不可能的,但二種產品之間存在許多差異,在轉換時需要加以解決。根據應用程序的規模,這種轉換可能需要大量的時間。盡管無需重新編寫所有的應用程序,但需要完成的工作并不少。
我目前還沒有發現這二種數據庫間轉換的更簡單的方法。由于二種產品在許多方面都非常相似,我們非常容易成功地將Sybase數據庫轉換為SQL Server數據。
新聞熱點
疑難解答