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 MSDN
l Microsoft SQL SERVER Online Book
l 《Delphi COM 深入编程》(美) Eric Harmon 机械工业出版社