SQL-DMO簡介
Microsoft SQL Server是當前比較流行的數據庫管理系統。隨著SQL Server的不斷完善與發展,以及與微軟本身的Windows系列操作系統的完美結合,在Windows平台上提供較好的性能和易用性,因此越來越受到人們的重視。 SQL-DMO的全稱是SQL Distributed Management Objects。它是一個集合,包含一組有雙重接口的COM。通過SQL-DMO我們可以控制操作SQL Server 的數據庫引擎和復制管理。由於SQL-DMO是一組COM,所以任何可以使用COM的開發工具都可以使用它,包括VB、Delphi、VC、BCB、asp等等幾乎包括所有的Windows平台下的開發工具。
SQL-DMO用途
我們為什麼需要使用SQL-DMO對數據庫進行管理呢?難道我們用EnterPRise Manager和T-SQL 腳本對數據庫進行管理還不夠嗎?用SQL-DMO可以進行靈活、可定制、高效的數據庫管理活動。由於SQL-DMO提供的是SQL SERVER的管理接口,通過編程,你就可以按照自己的需求,定制管理活動。舉個例子,如果我們管理的是一個大型組織,裡面有很多個SQL Server實例。現在要給組織中所有的SQL Server實例添加一個用戶,若通過Enterprise Manager手工給每個SQL Server實例進行添加用戶話就是一個費時費力而且容易出現人為錯誤的操作,若使用SQL-DMO編程實現話,用一個循環操作就可以簡單高效的完成。在作者看來,更為重要的是:使用SQL-DMO可以管理MSDE(Microsoft SQL Server Desktop Engine)。 MS SQL SERVER價格昂貴,而MSDE是免費的。在一些中小型應用中,MSDE已經足夠。但是,由於MSDE只提供數據庫引擎不提供可視化的管理界面,無法對MSDE中的數據庫進行常規管理,限制了MSDE的適用範圍。此時如果我們使用SQL-DMO就可以提供自己的數據庫管理界面,這樣就能對MSDE中的數據庫進行一定的常規管理。如果不考慮時間和成本的話,完全可以做出一個功能類似於Enterprise Manager的管理界面。實際上Enterprise Manager的絕大部分功能也是通過使用SQL-DMO實現的。 (其中用到SQL-NS(SQL-Namespace,其也是一個Com對象集合,提供了對SQL Server內對象名字空間的訪問功能),但是SQL-NS本身也是架構在SQL-DMO之上的)
SQL-DMO宿主和構成
SQL-DMO的宿主是SQLDMO.DLL,位於X:/Program Files/Microsoft SQL Server/80/Tools/Binn下。另外它還需要以下一些文件:l
SQLDMO.DLL (主類型庫) l
SQLDMO.RLL (語言資源
文件) l
SQLSVC.DLL (數據庫管理用類型庫) l
SQLSVC.RLL (語言資源文件) l
SQLUNIRL.DLL (Unicode重定向層) l
SQLRSLD.DLL (資源載入用) l
ODBC (包括ODBC32.DLL, SQLSRV32.DLL, ODBCBCP.DLL等等)這裡是一個調用結構的說明(圖1):
圖1 SQL-DMO的調用結構
SQL-DMO的對象樹
我們首先來看一下SQL-DMO龐大復雜的對象樹(見圖3):SQLServer對像是這個對象樹的主幹,這個主幹下主要有三個大的分支:l Database分支,其下的一系列的對象實現了SQLServer中數據庫架構以及維護任務。 l JobServer分支,其下的一系列對象實現了SQL Server代理( Agent)服務。 l Replication分支,其下的一系列的作對象實現了SQL Server的複制服務。還需要說明的有:l 對象樹沒有列出Application對象,其實這是一個比較重要的對象。任何一個SQL-DMO對像都有一個屬性指向Application對象。 Application對象代表著一個全局的應用,其包含了Servers和ServerGroups兩個集合對象。如圖2:圖2 Application對象l 對象樹僅僅表示了SQL-DMO的結構並沒有列出所有的對象,例如NameList對象、Servergroup對像等。 SQL-DMO對象樹結構複雜,對象繁多,在這裡不可能對每個對象每個屬性每個方法一一加以介紹說明,一些方法的說明會在下面具體的代碼中解釋。 圖3 SQL-DMO的對象樹
Delphi封裝SQL-DMO的實現
下面就介紹筆者利用Delphi實現的對SQL-DMO封裝的組件TDBCTRL。筆者由於在某個項目中需要一個免費的數據庫引擎,最終選擇了MSDE,但是MSDE沒有管理界面,僅僅是個引擎而已。所以就有了給MSDE提供簡單明了的管理界面這個需求。我們不需要提供Enterprise Manager那麼多的管理功能,我們只需要提供最常用的功能就足夠了。考慮到易使用性和可擴展性,決定用組件的形式提供。實現的組件提供了對SQL-DMO的一層包裝,把一些常用的功能進行封裝,簡化使用。注意,編譯此組件需要引入SQL-DMO的類型庫,並生成對應的描述代碼。代碼當中的包含很多Delphi對Com對象的一些常規用法和慣用表示法。在這裡不討論Delphi是如何使用COM了,讀者可以參考相關書籍。此組件包含如下屬性:property Host:String read FHost write FHost;//主機名、即所要連接的SQL Server實例名property PassWord:String read FPWD write FPWD; //用於連接的用戶密碼property Login:String read FLogin write FLogin; //用於連接的用戶名property LoginSecure:boolean read FLoginSecure write FLoginSecure; //登錄模式、True代表使用NT驗證模式,false代表SQL Sever驗證模式另外此組件聚合了一個SqlServer對象,用有一個私有數據成員:sqlserver來保存。其類型為_SqlServr.此組件的構造函數和析構函數也十分簡單。構造函數就是連接創建sqlserver對象。析構函數也僅僅是完成對sqlserver對象的析構。 constructor TDBCTRL.Create(AOwner: TComponent);begin inherited;sqlserver:=coSqlserver.Create; //CoSqlserver是_SqlServer的類工廠end;destructor TDBCTRL.Destroy;begin sqlserver:=nil; //把此對象設置為nil後,Delphi會在幕後完成Com對象的析構。 inherited;end;如果我們要對某個SQL Server實例進行管理和操作,首先我們要連接到這個實例。下面的ConnectToServer函數就實現瞭如何連接到一個SQL Server實例的功能。 function TDBCTRL.ConnectToServer: Boolean;begin SqlServer.LoginSecure:= FLoginSecure;// 設置是否是NT驗證模式,如果是True就會忽略Login和Password; try sqlServer.Connect(FHost,FLogin,FPWD); Result:=True ; Except On E:EOleException do begin ShowMessage(e.Message); result:=false; end; end;end;連接完成後,就取得了對此實例的控制(根據所登錄的用戶,會有不同的控制權限)。下面列出的一些方法展示了一些功能。 GetTableList方法取得某個數據庫的所有的表名,放在一個TStringList中返回。 function TDBCTRL.GetTableList(DBName: String; var TableList: TStringList): Boolean;var NowDB:_DataBase; //數據庫NowTable:_Table; //表I:integer;begin try TableList.Clear ; //清空StringList NowDB:=SqlServer .Databases.Item(DBName,Sqlserver);//根據數據庫名取得Database對象for I:=1 to NowDB.Tables.Count do begin NowTable:=NowDB.Tables.Item(I,0); TableList.add (NowTable .Name); end; //取的這個數據庫中所有的表名字,添入TStringList中result:=True; Except TableList.Clear ; result:=False; end;end;類似的,用相似的方法可以以取得數據庫中所有的視圖(Views)、一個表或視圖的所有字段(Columns)、一個數據庫的所有數據文件組以及數據文件(FileGroups、DBFiles)等等,這些可以具體參考SQL-DMO的對象結構樹。對SQL-DMO對象的使用可以遵循以下的基本步驟:通過上層對象取得某個對像或集合對象,然後使用對像或取得集合對像中某一個對象再使用。一般來說,如果是集合對像都有一個Item方法,可以根據Index或Name返回集合成員對象。需要注意的是Index是從1開始的而不是從0開始的。上面的這些方法都是演示如何從數據庫取得信息,下面我再演示一個方法,此方法的功能是備份數據庫到一個文件。通過這個方法來展示如何對數據庫進行維護操作的。 function TDBCTRL.BackupDB(DBName, BackupFile: String): Boolean;//傳入的參數為欲備份的數據庫名和備份文件名var dmoBack:_Backup; //備份對象backupdrv:_backupdevice; //備份設備對象begin //設置備份設備try DeleteFile(BAckUPFile); //若備份文件已經存在就刪除之try dmoBack:=coBackup.create; backupdrv:=coBackupDevice.Create ; //創建對象backupdrv.name:=DBName+'Bak'; //指定備份設備的名字backupdrv.Type_ :=SQLDMODevice_DiskDump; backupdrv.PhysicalLocation :=BackupFile ; //添加備份設備try sqlServer.BackupDevices.Add(backupdrv); except //由於這裡的異常不會返回值,沒有辦法,只能認為添加異常是由於已經存在這個備份集end; //進行備份dmoBack.action:=SQLDMOBackup_Database; dmoBack.database:=DBName; dmoBack.Devices :=DBName+'Bak'; dmoBack.SQLBackup(sqlserver) ; Result: =True; Except On E:EOleException do begin ShowMessage(e.Message); result:=false; end; end;finally dmoBack:=nil; backupdrv:=nil;end;end;另外,我還要舉一個例子來說明如何使用剛開始提到的Application對象。這個方法是取得所有可用(也就是可到達可連接)的Sql Server實例的名字。 function TDBCTRL.GetServerList(var ServerList: TStringList): Boolean;var App:_Application; //Application對象NList:NameList; //這個NameList也是SQL-DMO中的一個對象I:integer;begin try App:=CoApplication.Create ; NList:=App.ListAvailableSQLServers; //取得所有可用的SQLServer實例名for I:=0 to NLIst.Count-1 do ServerList.Add(NList.Item(I)); finally App:=nil; //釋放對象end;end;當然,TDBCTRL組件還有很多方法,但是代碼實現相似,比如對應備份的恢復方法,對應於連接的斷開連接方法,我也就不一一列舉了。讀者可以參考示例代碼和SQL SERVER的Online Book,舉一反三,實現自己想要的功能。如果需要此組件的全部代碼可以問筆者索要。
其它說明
SQL-DMO的2000版本完全兼容於SQL SERVER7.0和SQL SERVER 2000。但是提供80多個新的接口用來支持SQL SERVER 2000的新特性。這些新的接口結尾都帶”2”,這些是原來的SQL SERVER 7.0中那些接口的超集。也就是說如果要使用SQL SERVER 2000的新特性就要使用末尾帶”2”的接口。
參考書目
l Microsoft MSDNl Microsoft SQL SERVER Online Bookl 《Delphi COM 深入編程》(美) Eric Harmon 機械工業出版社