我最近參與了將壹個Sybase數據庫移植到MicrosoftSQLServer
2000上的項目,我在這壹項目上獲得的經驗,將對Sybase數據庫管理員把Sybase數據庫移植到SQLServer2000平臺上有壹定的幫助。
盡管二者之間的壹些差別是相當大的,例如Sybase數據庫管理系統中的存儲過程在SQL
Server就不能被編譯,而其它差別則不太大。在完成這壹轉換前,對腳本文件和存儲過程中編程邏輯的行為和結果進行測試是很有必要的。
在下面的部分中,我們將討論這二種數據庫系統之間的壹些主要的不同點,在移植的規劃階段,我們必須仔細研究這些區別。
數據兼容模式
對SQLServer2000和Sybase之間的壹些兼容性差別的壹個臨時性解決方案是改變SQL
Server中的數據庫兼容性級別,使之與Sybase相符。為此,我們可以使用sp_dbcmptlevel存儲過程。
下面表中的語句和結果顯示出不同版本數據庫之間的差別:
(Untitled-1)
註意:
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_dbcmptlevelpubs
這壹行代碼返回下面的結果:
Thecurrentcompatibilitylevelis70.(當前的兼容性級別為70。)
現在我們來看壹下另外壹個例子:
sp_dbcmptlevelpubs,65
它返回如下的結果:
DBCCexecutioncompleted.(DBCC執行結束。)
果DBCC打印出錯誤信息,則需要與系統管理員聯系。我們可以使用rerunsp_dbcmptlevel驗證pubs數據庫是否修改得正確:
sp_dbcmptlevelpubs
它返回下面的結果:
Thecurrentcompatibilitylevelis65(當前的兼容性級別為65。)
除了上面的例子外,兼容性級別的差別還擴展到了保留字。Sybase和SQL
Server都有許多不能被用作數據庫中對象名字的的保留字,二種產品的保留字相似,但並不完全相同。
由於能夠在Sybase中使用的對象可能不能在SQLServer中使用,這壹問題使得由Sybase向SQL
Server的移植憑添了許多困難。下面是在SQL
Server中是保留字,而在Sybase中不是保留字的詞匯清單。
註意:名字為下列清單中詞匯的Sybase數據庫中的對象在移植到SQL
Server數據庫時必須換為其它名字。
BACKUPCOLUMNCOMMITTEDCONTAINSCONTAINSTABLE
CROSSCURRENT_DATE
CURRENT_TIMECURRENT_TIMESTAMPCURRENT_USER
DENYDISTRIBUTEDFILEFLOPPY
FREETEXT
FREETEXTTABLEFULLIDENTITYCOLINNERJOIN
事務管理模式
SybaseSQLServer
Setchained[on:off]Setimplicit_transactions
[on:off]
在Sybase中使用下面的代碼判斷事務模式:
SELECT@@tranchained
GO
下面是可能返回的結果:
0表明使用的是非鏈鎖式事務模式
1表明連接運行在鏈鎖模式下
在SQLServer中使用下面的代碼判斷事務模式:
IF(@@options&2)>0
on
ELSE
PRINToff
下面是可能的返回結果:
0off
>0on
隔離水平
在壹個關系數據庫這樣的多線程應用軟件中,數據庫引擎對運行的進程間的數據是如何被隔離的管理是非常重要的,在表示隔離水平時,Sybase和SQL
Server的語法是不同的。下面的表格表明了Sybase和SQLServer在表示隔離水平時的差別。
SybaseSQL
Server
0READUNCOMMITTED
1READCOMMITTED
2REPEATABLEREAD
3
SERIALIZABLE
遊標語法
二種產品中存儲過程的創建和執行基本相似,但在移植時,遊標語句中的壹些例外是我們應當註意的。下面是壹個例子:
CREATEPROCEDUREsql_cursorAS
DECLARE@lnamechar(20),@fname
char(20)
DECLAREmycursorCURSORFOR
SELECTau_lname,au_fnameFROM
authors
OPENmycursor
FETCHFROMmycursorINTO@lname,@fname
WHILE@@
FETCH_STATUS=0
/*Sybase數據庫使用@SQLSTATUS而不是@@FETCH_STATUS*/
BEGIN
FETCHFROMmycursorINTO@lname,@fname
/*
**
這裏應當是壹些業務邏輯
*/
END
CLOSEmycursor
DEALLOCATE/*
Sybase數據庫在這裏需要CURSOR這個詞*/mycursor
SybaseSQLServer
Fetch命令執行成功00
Fetch命令執行失敗1-2
沒有可存取的記錄了2
-1
退回觸發器
SQLServer中不存在這個命令,因此在向SQL
Server移植時,使用了ROLLBACKTRIGGER命令的Sybase存儲過程必須被進行修改。在修改帶有觸發器的數據庫表中的數據時,使用ROLLBACK
TRIGGER命令容易引起誤解,壹個ROLLBACK
TRIGGER命令只退回觸發器以及觸發觸發器的數據修改,如果已經被提交了,則事務的其它部分會繼續,被寫到數據庫中。因此,事務中的所有語句可能沒有被成功地完成,但數據已經被提交了。
下面是Sybase數據庫中壹個使用ROLLBACK
TRIGGER的樣例觸發器:
CREATETABLEtable1(aint,bint)
GO
CREATETRIGGERtrigger1ontable1
FORINSERT
AS
IFEXISTS(SELECT1FROMinsertedWHEREa=
100)
BEGIN
ROLLBACKTRIGGERwithRAISERROR50000Invalidvalueforcolumn
a
END
INSERTINTOtable2
SELECTa,GETDATE()from
inserted
RETURN
GO
在上面的代碼中,除非a=100,則所有插入table1的數據也被作為審計行插入table2中,如果a=100,ROLLBACK
TRIGGER命令被觸發,而INSERT命令沒有被觸發,批命令的其它部分繼續執行,這時會出現錯誤信息,表明在壹個INSERT命令中出現了錯誤。下面是所有的INSERT命令:
BEGINTRAN
INSERTINTOtable1VALUES(1,1)
INSERTINTOtable1VALUES
(100,2)
INSERTINTOtable1VALUES(3,3)
GO
SELECT*FROMtable1
在執行這些命令後,table1和table2二個數據庫表將各有2個記錄,Table1表中的值為1,1以及3,3,由於ROLLBACK
TRIGGER命令,第二個INSERT命令沒有執行;Table2表中的值為1,(當前日期)以及3,(當前日期),由於當a=100時ROLLBACK
TRIGGER被觸發,觸發器中的所有處理被中止,100沒有被插入到Table2表中。
在SQL
Server中模擬這壹操作需要更多的代碼,外部的事務必須與保存點同時使用,如下所示:
CREATEtrigger1ontable1FOR
INSERT
AS
SAVETRANtrigger1
IFEXISTS(SELECT*FROMinsertedWHEREa
=100)
BEGIN
ROLLBACKTRANtrigger1
RAISERROR50000
ROLLBACK
END
INSERTINTOtable2
SELECTa,GETDATE()FROM
inserted
GO
這壹觸發器以壹個存儲點開始,ROLLBACKTRANSACTION只退回觸發邏輯,而不是整個事務(規模要小於Sybases數據庫中的ROLLBACK
TRIGGER語句。對批命令的修改如下:
BEGINTRAN
SAVETRANsave1
INSERTINTOtable1
VALUES(1,1)
IF@@error=50000
ROLLBACKTRANsave1
SAVETRAN
save2
INSERTINTOtable1VALUES(100,1)
IF@@error=50000
ROLLBACK
TRANsave2
SAVETRANsave3
INSERTINTOtable1VALUES(3,3)
IF@@error
=50000
ROLLBACKTRANsave3
COMMITTRAN
我們可以發現,改變不可謂不大。由於ROLLBACKTRIGGER命令能夠使任何批命令不能成功執行,因此在移植的SQL
Server存儲過程代碼中必須包括另外的邏輯,根據ROLLBACK
TRIGGER的使用,這可能是壹個艱巨而必要的任務,沒有什麽捷徑可走。如果在移植後所有的ROLLBACKTRIGGER命令被改變為ROLLBACK
TRANSACTION,觸發器的執行也會發生變化,因此我們應當十分小心。
命令優化
SQL
Server能夠對SELECT、INSERT、UPDATE和DELETE命令進行優化,Sybase數據庫則只支持對SELECT命令進行優化。下面是SQL
Server和Sybase在GUI方面的對比:
SybaseSQL
Server
使用被稱作SHOWPLAN的基於文本的查詢分析工具使用Query
Analyzer。
在ISQL中啟動SHOWPLAN的命令按鈕多QueryAnalyzer中啟動SHOWPLAN_ALL或
SHOWPLAN_TEXT的命令
SETSHOWPLANONSETSHOWPLAN_ALL
GOGO
臨時數據庫表的名字
表名字的類型 最大長度
SQLServer表名字 128
SQL
Server臨時表名字 116
Sybase表名字 30
Sybase臨時表名字 13
數據類型
數據類型SybaseSQLServer
char(n)2558000
varchar(n)255
8000
nchar(n)2554000
nvarchar(n)2554000
binary255
8000
varbinary2558000
註意:
1)SQL
Server中的bit類型數據的值可以被設置為0、1或NULL。
2)Sybase中的bit類型數據的值不可以被設置為NULL。
同壹性列
SybaseSQLServer
Numeric(x,0)Tinyint,smallint,int,decimal(x,0)or
numeric(x,0)
打印語法
在進行移植時,所有使用替換語法的打印語句必須被改變為RAISERROR語句。
結論
將Sybase數據庫轉換為SQL
Server數據庫並非是不可能的,但二種產品之間存在許多差異,在轉換時需要加以解決。根據應用程序的規模,這種轉換可能需要大量的時間。盡管無需重新編寫所有的應用程序,但需要完成的工作並不少。
我目前還沒有發現這二種數據庫間轉換的更簡單的方法。由於二種產品在許多方面都非常相似,我們非常容易成功地將Sybase數據庫轉換為SQL
Server數據。