您的位置:首页 > 数据库

数据库 远程备份和恢复

2011-12-29 13:39 513 查看
在论坛混了这么多年, 看到的一个很明显的趋势是, 用VFP和SQL SERVER来做系统的网友越来越多。怎么从VFP里来操作或者管理SQL SERVER也成为很多人关心的问题。 对SQL SERVER的数据操作,可以用视图,SPT或者ADO来做,但对服务器本身的管理,似乎只有用SPT来发送一些命令了。其实, 微软为客户端操作SQL SERVER开发了一套完整的工具, 这就是SQL - DMO (Distributed Management Objects). 这是一套COM组件,可以在各种语言里使用,
VFP里自然也可以用了。

我准备花点时间,写些这方面的介绍文章,然后做个实例,算是我通过MCDBA后,给大家的礼物吧。下面的介绍和例子,是针对SQL SERVER 2000和VFP7的。

一. 用SQL -DMO的必要性

大部分VFPER开发的程序,都是中小规模的系统,因为这是VFP最适用的范围。而这样的系统,很多情况下是,客户端没有专业IT人士维护,更不要说专门的DBA了。对于使用SQL SERVER的系统,就带来了一些问题。 SQL SERVER是一套比较大的数据库专业软件, 是经常需要维护和清理的,而我们这些系统开发者, 总不能老跑去用户那里做维护工作吧,尤其对商业软件来说,这是很大的成本了。如果可以把对SQL SERVER的维护工作放到自己的程序里,甚至把SQL SERVER的安装无缝并入到自己的程序的安装包里,相信大家都会很乐意的。
DMO的功能就能满足我们的这些需要。通过它,可以从程序里用命令方式来操作SQL SERVER:停止/启动服务,建立数据库和表,添加用户和权限,备份/恢复数据库,数据导入/导出/发布... DMO的作用就是把我们能在Enterprise Manager里完成的功能,完全用代码来做.

二. 微软的桌面数据引擎 (Desktop Database Engine)

我们都知道SQL SERVER 2000有四个版本: 个人版,开发者版,标准班和企业版. 其实,还有一个版本,就是桌面数据引擎(DDE)。 DDE几乎具有

SQL SERVER标准版和企业版的所有功能,不能支持的只是少数几个不常用的功能。而它和其它版本的区别是, DDE没有任何图形管理界面,没有ENTERPRISE MANAGER,没有查询分析器等等工具。 对它的管理,主要是通过DMO或者专门的API来进行,它的另一个优点是, 提供了安装程序,可以直接加到第3方软件里进行安装。每个版本的SQL SERVER CD里都带有DDE, 在MSDE目录下,运行SETUP程序就可以安装。至于怎么把它加到自己的程序里安装,大家查一下SQL SERVER的帮助文件就可以找到。

DDE的限制是: 只适宜中小型系统(比如没有5个以上的用户同时连接和运行大型SQL命令), 如果同时访问的用户很多, DDE就会比正常的SQL SERVER慢了。

这样, DDE+DMO就可以实现我们上面所要求的功能了。这种做法甚至可以不让用户知道你是在使用SQL SERVER做为数据库。当然, DMO不是只能操作DDE,它可以操作所有版本的SQL SERVER。

三. DMO的安装

其实DMO主要就是一个DLL文件而已: SQLDMO.DLL。具体位置在C:/Program Files/Microsoft SQL Server/80/Tools/Binn目录里, 在同一目录里还有个帮助文件Sqldmo80.hlp. 如果你在程序里不能使用DMO, 找到这个DLL文件,注册一下,就可以了。另外在C:/Program Files/Microsoft SQL Server/80/Tools/ Devtools/Samples/Sqldmo 目录下,有SQLDMO的例子,但都是VB和VC++的。VB的例子和VFP很接近的.

四. 初步接触DMO

在这里写几个简单的句子,来看看DMO的强大. 这些命令可以直接在命令窗口里一行一行测试, 只是用它们来显示数据库的信息。至于添加数据库,数据表,备份和恢复等比较复杂的功能,得在实例里做。

oServer=CreateObject("SQLDMO.SQLServer") &&建立SERVER对象

oServer.Connect("Snoopy","sa","778899") &&连接到你的服务器

? oServer.Databases.Count &&显示服务器上的数据库总数

? oServer.Databases.Item(1).Name &&显示第一个数据库的名字

oDB=oServer.Databases("PUBS") &&建立数据库对象

? oDB.Tables.Count &&显示库里表的数目

oTable=oDB.Tables("Titles") &&建立表对象

? oTable.Rows &&显示表里的记录数

? oTable.Columns.Count &&显示表的列数

**显示列的属性

? oTable.Columns(1).Name

? oTable.Columns(1).type

? oTable.Columns(1).Datatype

? oTable.Columns(1).Identity

? oTable.Columns(1).InPrimaryKey

例子:

Backup和Restore数据库

oServer=CreateObject("SQLDMO.SQLServer") &&建立SERVER对象

oServer.Connect("Snoopy","sa","778899") &&连接到你的服务器

**备份

oBackup=CreateObject("SQLDMO.Backup") &&建立备份对象

oBackup.Database="PUBS" &&指定备份数据库

oBackup.Password="8899" &&给备份文件加密码

oBackup.Files="D:/Temp/PUBBack.Dat" &&指定目标文件

oBackup.SQLBackup(oServer) &&运行备份命令,速度很快的

**备份恢复

oRestore=CreateObject("SQLDMO.Restore")

oRestore.Database="PUBS"

oRestore.Files="D:/Temp/PUBBack.Dat"

oRestore.SQLRestore

oRestore.SQLRestore(oServer) &&先试不加密码,备份失败

oRestore.Password="8899"

oRestore.SQLRestore(oServer)

SQL SERVER提供几种数据库备份方式,

一种是完整备份 (Full Backup), 第二种是差异备份(Differential Backup), 第三种是日志备份, 第四种是文件备份

完整备份是把整个数据库做个备份,差异备份只是备份进行了完整备份后数据库里的新变化。当数据库很大时, 完整备份很费空间和时间,可以根据情况定期做,比如每周或者每月做一次完整备份。 其它时间可以进行差异备份,比如每天一次,或者半天一次, 也可以结合进行日志备份。文件备份是直接备份数据库的数据和日志文件。和在操作系统里做备份一样.

在恢复的时候,只要先恢复完整备份,然后恢复最后一个差异备份就可以。如果有日志备份,还需要恢复差异备份后所做的日志备份。

备份种类通过 备份对象的Action属性来决定.

oBackup.Action=0 && 参数: 0 - 完整备份,1- 差异备份, 2- 文件备份, 3 -日志备份

Server对象的一些属性和方法

属性

AutoReConnect: 当连接断开,后是否自动重连

ConnectionID: 本连接的ID

HostName: 本地机器的名字

Isdbcreator, Isdiskadmin, Isprocessadmin, Issecurityadmin, Isserveradmin, Issetupadmin, Issysadmin: 返回当前连接用户是否属于某类SERVER ROLE,比如是不是SA

LoginTimeout: 决定连接超时时间,默认为60秒

SaLogin: 当前连接是不是SA

Status:服务器当前状态

VersionMajor,VersionMinor: SQL SERVER的版本号

方法:

AttachDB, DetachDB: 添加或者剥离数据库

Connect, Disconnect, Close: 连接, 断开,或者关闭当前服务器对象(oServer)

VerifyConnection: 测试当前连接是否断开

Reconnect: 重新连接

Start, Stop, Shutdown: 用来启动,停止或者关闭服务器

BeginTransaction, RollbackTransaction, CommitTransaction: 操作事务

EnumServerAttributes: 返回服务器的大部分设置参数

EnumLocks: 返回服务器上所有的加锁进程

KillProcess: 强行中断一个进程

在VFP里来操作和管理SQL SERVER (2) (介绍SQL-DMO)

用DMO来建立任务,并让它定时运行. 执行环境必须是NT或者WINDOWS 2000, 因为需要运行SQL AGENT

***建立任务(JOB)

oJob=CreateObject("SQLDMO.Job") &&创建任务对象

ojob.Name="Pubs_Daily_Backup" &&任务名称

oServer.JobServer.Jobs.Add(oJob) &&加到SQL SERVER的任务里

oJob.BeginAlter &&开始定义任务

oJobStep=CreateObject("SQLDMO.JobStep") &&创建任务步骤对象

oJobStep.Name = "Step_1" &&步骤名称

oJobStep.StepID = 1 &&步骤号码

oJobStep.DatabaseName="Pubs" &&数据库名称

oJobStep.SubSystem= "TSQL" &&任务类型,可以是TSQL或者操作系统命令(CmdExec), 或者ActiveScripting

cFName="PubBack"+Dtoc(Date(),1)+".dat" &&备份目标文件名

oJobStep.Command ="Backup database Pubs to Disk='D:/Temp/"+cFname+"' With Password='7788'" &&执行备份的TSQL命令

oJobStep.OnFailAction = 2 && 如果任务失败退出。也可以设成发送EMAIL或者用NT里的NETSEND发信息

oJobStep.OnSuccessAction= 1 && 如果任务成功,退出。

oJob.JobSteps.Add(oJobStep) &&添加任务步骤

oJob.StartStepID = 1 &&从第一步开始执行,对多步骤的任务起作用

oJob.DoAlter &&保存修改

***把任务加到SCHEDULER里

oJobSchedule =CreateObject("SQLDMO.JobSchedule") &&创建Schedule对象

oJob = oServer.JobServer.Jobs("Pubs_Daily_Backup")&&创建任务对象

oJobSchedule.Name = "Daily_Execution" &&名称

oJobSchedule.Schedule.FrequencyType= 4 && 运行频率, 4是每日运行

oJobSchedule.Schedule.FrequencyInterval = 1 &&运行间隔, 1是每天

oJobSchedule.Schedule.ActiveStartDate =Dtoc(Date(),1) &&开始日期(今天), 必须是yyyymmdd格式

oJobSchedule.Schedule.ActiveStartTimeOfDay = "233000" &&开始时间(晚上11点30), 必须是 hhmmss格式

**下面2句设置是使任务永不过期

oJobSchedule.Schedule.ActiveEndDate=99991231 &&no end date

oJobSchedule.Schedule.ActiveEndTimeOfDay =235959 &&No end time

添加任务到SCHEDULE里

oJob.BeginAlter

oJob.JobSchedules.Add(oJobSchedule)

oJob.DoAlter

上述命令我在VFP7里都测试成功,在SQL SERVER里也看到了新添加的命令和运行设置,但因为我是用的WINDOWS ME,没法测试任务是否真的运行了。哪位有环境,可以帮我试试

下面这个帖子中的存储过程比较麻烦,不过调用起来比较简单。

------------------------------------------------

SQL SERVER2000数据库备份和恢复存储过程

我自己写的2个过程和一个函数,用于SQL SERVER2000数据库备份和恢复

拿出来和大家交流一下,过程和函数的详细说明在代码中

谢谢

/*备份数据库的过程*/

if exists(

select * from sysobjects

where name='pr_backup_db' and xtype='p'

)

begin

drop proc pr_backup_db

end

go

create proc pr_backup_db

@flag varchar(20) out,

@backup_db_name varchar(128),

@filename varchar(1000) --路径+文件名字

as

declare @sql nvarchar(4000),@par nvarchar(1000)

if not exists(

select * from master..sysdatabases

where name=@backup_db_name

)

begin

select @flag='db not exist' /*数据库不存在*/

return

end

else

begin

if right(@filename,1)<>'/' and charindex('/',@filename)<>0

begin

select @par='@filename varchar(1000)'

select @sql='BACKUP DATABASE '+@backup_db_name+' to
disk=@filename with init'

execute sp_executesql @sql,@par,@filename

select @flag='ok'

return

end

else

begin

select @flag='file type error' /*参数@filename输入格式错误*/

return

end

end

GO

说明:pr_backup_db过程是备份你的数据库

/*创建函数,得到文件得路径*/

if exists(

select * from sysobjects

where name='fn_GetFilePath' and xtype='fn'

)

begin

drop function fn_GetFilePath

end

go

create function fn_GetFilePath(@filename nvarchar(260))

returns nvarchar(260)

as

begin

declare @file_path nvarchar(260)

declare @filename_reverse nvarchar(260)

select @filename_reverse=reverse(@filename)

select @file_path=substring(@filename,1,len(@filename)+1-charindex('/',@filename_reverse))

return @file_path

end

GO

/*恢复数据库的过程*/

if exists(

select * from sysobjects

where name='pr_restore_db' and xtype='p'

)

begin

drop proc pr_restore_db

end

go

CREATE proc pr_restore_db

@flag varchar(20) out, /*过程运行的状态标志,是输入参数*/

@restore_db_name nvarchar(128), /*要恢复的数据名字*/

@filename nvarchar(260) /*备份文件存放的路径+备份文件名字*/

as

declare @proc_result tinyint /*返回系统存储过程xp_cmdshell运行结果*/

declare @loop_time smallint /*循环次数*/

declare @max_ids smallint /*@tem表的ids列最大数*/

declare @file_bak_path nvarchar(260) /*原数据库存放路径*/

declare @flag_file bit /*文件存放标志*/

declare @master_path nvarchar(260) /*数据库master文件路径*/

declare @sql nvarchar(4000),@par nvarchar(1000)

declare @sql_sub nvarchar(4000)

declare @sql_cmd nvarchar(100)

declare @sql_kill nvarchar(100)

/*

判断参数@filename文件格式合法性,以防止用户输入类似d: 或者 c:/a/ 等非法文件名

参数@filename里面必须有'/'并且不以'/'结尾

*/

if right(@filename,1)<>'/' and charindex('/',@filename)<>0

begin

select @sql_cmd='dir '+@filename

EXEC @proc_result = master..xp_cmdshell @sql_cmd,no_output

IF (@proc_result<>0) /*系统存储过程xp_cmdshell返回代码值:0(成功)或1(失败)*/

begin

select @flag='not exist' /*备份文件不存在*/

return /*退出过程*/

end

/*创建临时表,保存由备份集内包含的数据库和日志文件列表组成的结果集*/

create table #tem(

LogicalName nvarchar(128), /*文件的逻辑名称*/

PhysicalName nvarchar(260) , /*文件的物理名称或操作系统名称*/

Type char(1), /*数据文件 (D) 或日志文件 (L)*/

FileGroupName nvarchar(128), /*包含文件的文件组名称*/

[Size] numeric(20,0), /*当前大小(以字节为单位)*/

[MaxSize] numeric(20,0) /*允许的最大大小(以字节为单位)*/

)

/*

创建表变量,表结构与临时表基本一样

就是多了两列,

列ids(自增编号列),

列file_path,存放文件的路径

*/

declare @tem table(

ids smallint identity, /*自增编号列*/

LogicalName nvarchar(128),

PhysicalName nvarchar(260),

File_path nvarchar(260),

Type char(1),

FileGroupName nvarchar(128)

)

insert into #tem

execute('restore filelistonly from disk='''+@filename+'''')

/*将临时表导入表变量中,并且计算出相应得路径*/

insert into @tem(LogicalName,PhysicalName,File_path,Type,FileGroupName)

select LogicalName,PhysicalName,dbo.fn_GetFilePath(PhysicalName),Type,FileGroupName

from #tem

if @@rowcount>0

begin

drop table #tem

end

select @loop_time=1

select @max_ids=max(ids) /*@tem表的ids列最大数*/

from @tem

while @loop_time<=@max_ids

begin

select @file_bak_path=file_path

from @tem where ids=@loop_time

select @sql_cmd='dir '+@file_bak_path

EXEC @proc_result = master..xp_cmdshell @sql_cmd,no_output

/*系统存储过程xp_cmdshell返回代码值:0(成功)或1(失败)*/

IF (@proc_result<>0)

select @loop_time=@loop_time+1

else

BREAK /*没有找到备份前数据文件原有存放路径,退出循环*/

end

select @master_path=''

if @loop_time>@max_ids

select @flag_file=1 /*备份前数据文件原有存放路径存在*/

else

begin

select @flag_file=0 /*备份前数据文件原有存放路径不存在*/

select @master_path=dbo.fn_GetFilePath(filename)

from master..sysdatabases

where name='master'

end

select @sql_sub=''

/*type='d'是数据文件,type='l'是日志文件 */

/*@flag_file=1时新的数据库文件还是存放在原来路径,否则存放路径和master数据库路径一样*/

select @sql_sub=@sql_sub+'move '''+LogicalName+''' to '''

+case type

when 'd' then case @flag_file

when 1 then File_path

else @master_path

end

when 'l' then case @flag_file

when 1 then File_path

else @master_path

end

end

+case type

when 'd' then @restore_db_name

+'_DATA'

+convert(sysname,ids) /*给文件编号*/

+'.'

+right(PhysicalName,3) /*给文件加入后缀名,mdf or ndf*/

+''','

when 'l' then @restore_db_name

+'_LOG'

+convert(sysname,ids) /*给文件编号*/

+'.'

+right(PhysicalName,3) /*给文件加入后缀名,mdf or ndf*/

+''','

end

from @tem

select @sql='RESTORE DATABASE @db_name FROM DISK=@filename with '

select @sql=@sql+@sql_sub+'replace'

select @par='@db_name nvarchar(128),@filename nvarchar(260)'

/*关闭相关进程,把相应进程状况导入临时表中*/

select identity(int,1,1) ids, spid

into #temp

from master..sysprocesses

where dbid=db_id(@restore_db_name)

if @@rowcount>0 --找到相应进程

begin

select @max_ids=max(ids)

from #temp

select @loop_time=1

while @loop_time<=@max_ids

begin

select @sql_kill='kill '+convert(nvarchar(20),spid)

from #temp

where ids=@loop_time

execute sp_executesql @sql_kill

select @loop_time=@loop_time+1

end

end

drop table #temp

execute sp_executesql @sql,@par,@db_name=@restore_db_name,@filename=@filename

select @flag='ok' /*操作成功*/

end

else

begin

SELECT @flag='file type error' /*参数@filename输入格式错误*/

end

GO

--run

--备份数据库test_database

declare @fl varchar(10)

execute pr_backup_db @fl out,'test_database','c:/test_database.bak'

select @fl

--恢复数据库,输入的参数错误

declare @fl varchar(20)

exec pr_restore_db @fl out,'sa','c:/'

select @fl

--恢复数据库,即创建数据库test_database的复本test_db

declare @fl varchar(20)

exec pr_restore_db @fl out,'test_db','c:/test_database.bak'

select @fl

以上过程和函数在MS SQL2000运行成功,由于MS SQL7不支持用户自定义函数和表变量,要在MS SQL7下使用可以把函数fn_GetFilePath改写成过

程,把过程pr_restore_db中的表变量改写为临时表即可运行,有兴趣的朋友可以试试!

1.数据备份:

Close All

Clear

mypath_old=Sys(5)+Sys(2003)

mypath_new=Alltrim(Alltrim(mypath_old)+'/MYDBCBF')

If !Directory("&MYPATH_new.")

Md &mypath_new.

Endif

Set Default To &mypath_new.

mydbf_old=Getfile('bak','','',1,'请输入或选定备份文件名')

If Len(mydbf_old)=0

=Messagebox('你刚才没有录入任何文件名,备份没有成功!!',32,'提示信息')

Set Default To &mypath_old.

Else

mydbf_path=Left(mydbf_old,At('/',mydbf_old,Occurs('/',mydbf_old))-1)

If !Directory("&MYDBF_path.")

Md &mydbf_path.

ENDIF

ERASE &MYDBF_old.

handle=SQLExec(con,"backup database mydbc to disk=?MYDBF_old")

Set Default To &mypath_old.

If handle>0

=Messagebox('(^_^)数据成功备份到【 '+mydbf_path+' 】文件夹下! ',64,'数据库备份')

Else

=Messagebox(Message(),16,'数据库备份')

Endif

Endif

二.恢复:

Close All

Clear

mypath_old=Sys(5)+Sys(2003)

mypath_new=Alltrim(Alltrim(mypath_old)+'/MYDBCBF')

Set Default To &mypath_new.

mydbf=Getfile('bak','','',1,'请选定要恢复的文件名')

Restore From mypath_old+'/myurl/url' Additive

sql_server=Alltrim(my_server)

sql_path=Alltrim(Right(sql_server,Len(sql_server)-Atc('/',sql_server)))

If Len(sql_path)=0

sql_restore_mdf='C:/Program Files/Microsoft SQL Server/MSSQL/Data/mydbc.MDF'

sql_restore_ldf='C:/Program Files/Microsoft SQL Server/MSSQL/Data/mydbc_log.ldf'

Else

sql_restore_mdf='C:/Program Files/Microsoft SQL Server/MSSQL$'+sql_path+'/Data/mydbc.MDF'

sql_restore_ldf='C:/Program Files/Microsoft SQL Server/MSSQL$'+sql_path+'/Data/mydbc_log.ldf'

Endif

*now_timer=1

Try

=SQLDisconnect(con)

Catch

Finally

Endtry

=SQLSetprop(0,"displogin",3) &&永不显示信任连接提示

myurl="driver=sql server;server="+Alltrim(my_server)+;

";uid=sa;pwd="+Alltrim(my_pwd)+;

";database=MASTER"

con_master=Sqlstringconnect(myurl)

If con_master<0

=Messagebox('<@_@>本机已与服务器失去连接,您将退出本系统!',16,'系统信息')

Else

handle=SQLExec(con_master,"RESTORE DATABASE mydbc FROM DISK=?MYDBF With Replace;

,Move 'MYDBC_DATA' To ?SQL_RESTORE_mdf';

,Move 'MYDBC_LOG' To ?SQL_RESTORE_LDF'")

If handle>0

=MESSAGEBOX('^_^数据恢复成功!',32,'数据恢复')

Try

=SQLDisconnect(con_master)

Catch

Finally

Endtry

=SQLSetprop(0,"displogin",3) &&永不显示信任连接提示

myurl="driver=sql server;server="+Alltrim(my_server)+;

";uid=sa;pwd="+Alltrim(my_pwd)+;

";database=mydbc"

con=Sqlstringconnect(myurl)

If con<0

=Messagebox('<@_@>本机已与服务器失去连接,您将退出本系统!',16,'系统信息')

Else

now_timer=0

Endif

Else

=Messagebox(Message(),16,'数据恢复')

Endif

Endif

Set Default To &mypath_old.

数据备份不用多作解释.对于数据恢复:

1.要注意在选定恢复文件时可能会改变当前路径.要在恢复数据后还原当前路径.

2.测试与数据源的连接.因为SQL2000的数据库MASTER等是自带的,只要测试能否连接上其中一个就行.

因为在恢复时可能找不到你要恢复的自定义数据库,所以要测试SQL2000的数据表.

3.SQL2000的安装可能有自定义实例这个也要考虑.比方说你的服务实例名是SERVER那SQL2000生成的文件夹是:MSSQL$SERVER而不是MSSQL

4.在恢复数据时要断开与当前数据库的连接(与上面所述,用SQL2000的自带数据库作为当前连接),否则会产生异常.

5.数据恢复成功后,要恢复与自定义数据库的连接.

在论坛混了这么多年, 看到的一个很明显的趋势是, 用VFP和SQL SERVER来做系统的网友越来越多。怎么从VFP里来操作或者管理SQL SERVER也成为很多人关心的问题。 对SQL SERVER的数据操作,可以用视图,SPT或者ADO来做,但对服务器本身的管理,似乎只有用SPT来发送一些命令了。其实, 微软为客户端操作SQL SERVER开发了一套完整的工具, 这就是SQL - DMO (Distributed Management Objects). 这是一套COM组件,可以在各种语言里使用,
VFP里自然也可以用了。

我准备花点时间,写些这方面的介绍文章,然后做个实例,算是我通过MCDBA后,给大家的礼物吧。下面的介绍和例子,是针对SQL SERVER 2000和VFP7的。

一. 用SQL -DMO的必要性

大部分VFPER开发的程序,都是中小规模的系统,因为这是VFP最适用的范围。而这样的系统,很多情况下是,客户端没有专业IT人士维护,更不要说专门的DBA了。对于使用SQL SERVER的系统,就带来了一些问题。 SQL SERVER是一套比较大的数据库专业软件, 是经常需要维护和清理的,而我们这些系统开发者, 总不能老跑去用户那里做维护工作吧,尤其对商业软件来说,这是很大的成本了。如果可以把对SQL SERVER的维护工作放到自己的程序里,甚至把SQL SERVER的安装无缝并入到自己的程序的安装包里,相信大家都会很乐意的。
DMO的功能就能满足我们的这些需要。通过它,可以从程序里用命令方式来操作SQL SERVER:停止/启动服务,建立数据库和表,添加用户和权限,备份/恢复数据库,数据导入/导出/发布... DMO的作用就是把我们能在Enterprise Manager里完成的功能,完全用代码来做.

二. 微软的桌面数据引擎 (Desktop Database Engine)

我们都知道SQL SERVER 2000有四个版本: 个人版,开发者版,标准班和企业版. 其实,还有一个版本,就是桌面数据引擎(DDE)。 DDE几乎具有

SQL SERVER标准版和企业版的所有功能,不能支持的只是少数几个不常用的功能。而它和其它版本的区别是, DDE没有任何图形管理界面,没有ENTERPRISE MANAGER,没有查询分析器等等工具。 对它的管理,主要是通过DMO或者专门的API来进行,它的另一个优点是, 提供了安装程序,可以直接加到第3方软件里进行安装。每个版本的SQL SERVER CD里都带有DDE, 在MSDE目录下,运行SETUP程序就可以安装。至于怎么把它加到自己的程序里安装,大家查一下SQL SERVER的帮助文件就可以找到。

DDE的限制是: 只适宜中小型系统(比如没有5个以上的用户同时连接和运行大型SQL命令), 如果同时访问的用户很多, DDE就会比正常的SQL SERVER慢了。

这样, DDE+DMO就可以实现我们上面所要求的功能了。这种做法甚至可以不让用户知道你是在使用SQL SERVER做为数据库。当然, DMO不是只能操作DDE,它可以操作所有版本的SQL SERVER。

三. DMO的安装

其实DMO主要就是一个DLL文件而已: SQLDMO.DLL。具体位置在C:/Program Files/Microsoft SQL Server/80/Tools/Binn目录里, 在同一目录里还有个帮助文件Sqldmo80.hlp. 如果你在程序里不能使用DMO, 找到这个DLL文件,注册一下,就可以了。另外在C:/Program Files/Microsoft SQL Server/80/Tools/ Devtools/Samples/Sqldmo 目录下,有SQLDMO的例子,但都是VB和VC++的。VB的例子和VFP很接近的.

四. 初步接触DMO

在这里写几个简单的句子,来看看DMO的强大. 这些命令可以直接在命令窗口里一行一行测试, 只是用它们来显示数据库的信息。至于添加数据库,数据表,备份和恢复等比较复杂的功能,得在实例里做。

oServer=CreateObject("SQLDMO.SQLServer") &&建立SERVER对象

oServer.Connect("Snoopy","sa","778899") &&连接到你的服务器

? oServer.Databases.Count &&显示服务器上的数据库总数

? oServer.Databases.Item(1).Name &&显示第一个数据库的名字

oDB=oServer.Databases("PUBS") &&建立数据库对象

? oDB.Tables.Count &&显示库里表的数目

oTable=oDB.Tables("Titles") &&建立表对象

? oTable.Rows &&显示表里的记录数

? oTable.Columns.Count &&显示表的列数

**显示列的属性

? oTable.Columns(1).Name

? oTable.Columns(1).type

? oTable.Columns(1).Datatype

? oTable.Columns(1).Identity

? oTable.Columns(1).InPrimaryKey

例子:

Backup和Restore数据库

oServer=CreateObject("SQLDMO.SQLServer") &&建立SERVER对象

oServer.Connect("Snoopy","sa","778899") &&连接到你的服务器

**备份

oBackup=CreateObject("SQLDMO.Backup") &&建立备份对象

oBackup.Database="PUBS" &&指定备份数据库

oBackup.Password="8899" &&给备份文件加密码

oBackup.Files="D:/Temp/PUBBack.Dat" &&指定目标文件

oBackup.SQLBackup(oServer) &&运行备份命令,速度很快的

**备份恢复

oRestore=CreateObject("SQLDMO.Restore")

oRestore.Database="PUBS"

oRestore.Files="D:/Temp/PUBBack.Dat"

oRestore.SQLRestore

oRestore.SQLRestore(oServer) &&先试不加密码,备份失败

oRestore.Password="8899"

oRestore.SQLRestore(oServer)

SQL SERVER提供几种数据库备份方式,

一种是完整备份 (Full Backup), 第二种是差异备份(Differential Backup), 第三种是日志备份, 第四种是文件备份

完整备份是把整个数据库做个备份,差异备份只是备份进行了完整备份后数据库里的新变化。当数据库很大时, 完整备份很费空间和时间,可以根据情况定期做,比如每周或者每月做一次完整备份。 其它时间可以进行差异备份,比如每天一次,或者半天一次, 也可以结合进行日志备份。文件备份是直接备份数据库的数据和日志文件。和在操作系统里做备份一样.

在恢复的时候,只要先恢复完整备份,然后恢复最后一个差异备份就可以。如果有日志备份,还需要恢复差异备份后所做的日志备份。

备份种类通过 备份对象的Action属性来决定.

oBackup.Action=0 && 参数: 0 - 完整备份,1- 差异备份, 2- 文件备份, 3 -日志备份

Server对象的一些属性和方法

属性

AutoReConnect: 当连接断开,后是否自动重连

ConnectionID: 本连接的ID

HostName: 本地机器的名字

Isdbcreator, Isdiskadmin, Isprocessadmin, Issecurityadmin, Isserveradmin, Issetupadmin, Issysadmin: 返回当前连接用户是否属于某类SERVER ROLE,比如是不是SA

LoginTimeout: 决定连接超时时间,默认为60秒

SaLogin: 当前连接是不是SA

Status:服务器当前状态

VersionMajor,VersionMinor: SQL SERVER的版本号

方法:

AttachDB, DetachDB: 添加或者剥离数据库

Connect, Disconnect, Close: 连接, 断开,或者关闭当前服务器对象(oServer)

VerifyConnection: 测试当前连接是否断开

Reconnect: 重新连接

Start, Stop, Shutdown: 用来启动,停止或者关闭服务器

BeginTransaction, RollbackTransaction, CommitTransaction: 操作事务

EnumServerAttributes: 返回服务器的大部分设置参数

EnumLocks: 返回服务器上所有的加锁进程

KillProcess: 强行中断一个进程

在VFP里来操作和管理SQL SERVER (2) (介绍SQL-DMO)

用DMO来建立任务,并让它定时运行. 执行环境必须是NT或者WINDOWS 2000, 因为需要运行SQL AGENT

***建立任务(JOB)

oJob=CreateObject("SQLDMO.Job") &&创建任务对象

ojob.Name="Pubs_Daily_Backup" &&任务名称

oServer.JobServer.Jobs.Add(oJob) &&加到SQL SERVER的任务里

oJob.BeginAlter &&开始定义任务

oJobStep=CreateObject("SQLDMO.JobStep") &&创建任务步骤对象

oJobStep.Name = "Step_1" &&步骤名称

oJobStep.StepID = 1 &&步骤号码

oJobStep.DatabaseName="Pubs" &&数据库名称

oJobStep.SubSystem= "TSQL" &&任务类型,可以是TSQL或者操作系统命令(CmdExec), 或者ActiveScripting

cFName="PubBack"+Dtoc(Date(),1)+".dat" &&备份目标文件名

oJobStep.Command ="Backup database Pubs to Disk='D:/Temp/"+cFname+"' With Password='7788'" &&执行备份的TSQL命令

oJobStep.OnFailAction = 2 && 如果任务失败退出。也可以设成发送EMAIL或者用NT里的NETSEND发信息

oJobStep.OnSuccessAction= 1 && 如果任务成功,退出。

oJob.JobSteps.Add(oJobStep) &&添加任务步骤

oJob.StartStepID = 1 &&从第一步开始执行,对多步骤的任务起作用

oJob.DoAlter &&保存修改

***把任务加到SCHEDULER里

oJobSchedule =CreateObject("SQLDMO.JobSchedule") &&创建Schedule对象

oJob = oServer.JobServer.Jobs("Pubs_Daily_Backup")&&创建任务对象

oJobSchedule.Name = "Daily_Execution" &&名称

oJobSchedule.Schedule.FrequencyType= 4 && 运行频率, 4是每日运行

oJobSchedule.Schedule.FrequencyInterval = 1 &&运行间隔, 1是每天

oJobSchedule.Schedule.ActiveStartDate =Dtoc(Date(),1) &&开始日期(今天), 必须是yyyymmdd格式

oJobSchedule.Schedule.ActiveStartTimeOfDay = "233000" &&开始时间(晚上11点30), 必须是 hhmmss格式

**下面2句设置是使任务永不过期

oJobSchedule.Schedule.ActiveEndDate=99991231 &&no end date

oJobSchedule.Schedule.ActiveEndTimeOfDay =235959 &&No end time

添加任务到SCHEDULE里

oJob.BeginAlter

oJob.JobSchedules.Add(oJobSchedule)

oJob.DoAlter

上述命令我在VFP7里都测试成功,在SQL SERVER里也看到了新添加的命令和运行设置,但因为我是用的WINDOWS ME,没法测试任务是否真的运行了。哪位有环境,可以帮我试试

下面这个帖子中的存储过程比较麻烦,不过调用起来比较简单。

------------------------------------------------

SQL SERVER2000数据库备份和恢复存储过程

我自己写的2个过程和一个函数,用于SQL SERVER2000数据库备份和恢复

拿出来和大家交流一下,过程和函数的详细说明在代码中

谢谢

/*备份数据库的过程*/

if exists(

select * from sysobjects

where name='pr_backup_db' and xtype='p'

)

begin

drop proc pr_backup_db

end

go

create proc pr_backup_db

@flag varchar(20) out,

@backup_db_name varchar(128),

@filename varchar(1000) --路径+文件名字

as

declare @sql nvarchar(4000),@par nvarchar(1000)

if not exists(

select * from master..sysdatabases

where name=@backup_db_name

)

begin

select @flag='db not exist' /*数据库不存在*/

return

end

else

begin

if right(@filename,1)<>'/' and charindex('/',@filename)<>0

begin

select @par='@filename varchar(1000)'

select @sql='BACKUP DATABASE '+@backup_db_name+' to
disk=@filename with init'

execute sp_executesql @sql,@par,@filename

select @flag='ok'

return

end

else

begin

select @flag='file type error' /*参数@filename输入格式错误*/

return

end

end

GO

说明:pr_backup_db过程是备份你的数据库

/*创建函数,得到文件得路径*/

if exists(

select * from sysobjects

where name='fn_GetFilePath' and xtype='fn'

)

begin

drop function fn_GetFilePath

end

go

create function fn_GetFilePath(@filename nvarchar(260))

returns nvarchar(260)

as

begin

declare @file_path nvarchar(260)

declare @filename_reverse nvarchar(260)

select @filename_reverse=reverse(@filename)

select @file_path=substring(@filename,1,len(@filename)+1-charindex('/',@filename_reverse))

return @file_path

end

GO

/*恢复数据库的过程*/

if exists(

select * from sysobjects

where name='pr_restore_db' and xtype='p'

)

begin

drop proc pr_restore_db

end

go

CREATE proc pr_restore_db

@flag varchar(20) out, /*过程运行的状态标志,是输入参数*/

@restore_db_name nvarchar(128), /*要恢复的数据名字*/

@filename nvarchar(260) /*备份文件存放的路径+备份文件名字*/

as

declare @proc_result tinyint /*返回系统存储过程xp_cmdshell运行结果*/

declare @loop_time smallint /*循环次数*/

declare @max_ids smallint /*@tem表的ids列最大数*/

declare @file_bak_path nvarchar(260) /*原数据库存放路径*/

declare @flag_file bit /*文件存放标志*/

declare @master_path nvarchar(260) /*数据库master文件路径*/

declare @sql nvarchar(4000),@par nvarchar(1000)

declare @sql_sub nvarchar(4000)

declare @sql_cmd nvarchar(100)

declare @sql_kill nvarchar(100)

/*

判断参数@filename文件格式合法性,以防止用户输入类似d: 或者 c:/a/ 等非法文件名

参数@filename里面必须有'/'并且不以'/'结尾

*/

if right(@filename,1)<>'/' and charindex('/',@filename)<>0

begin

select @sql_cmd='dir '+@filename

EXEC @proc_result = master..xp_cmdshell @sql_cmd,no_output

IF (@proc_result<>0) /*系统存储过程xp_cmdshell返回代码值:0(成功)或1(失败)*/

begin

select @flag='not exist' /*备份文件不存在*/

return /*退出过程*/

end

/*创建临时表,保存由备份集内包含的数据库和日志文件列表组成的结果集*/

create table #tem(

LogicalName nvarchar(128), /*文件的逻辑名称*/

PhysicalName nvarchar(260) , /*文件的物理名称或操作系统名称*/

Type char(1), /*数据文件 (D) 或日志文件 (L)*/

FileGroupName nvarchar(128), /*包含文件的文件组名称*/

[Size] numeric(20,0), /*当前大小(以字节为单位)*/

[MaxSize] numeric(20,0) /*允许的最大大小(以字节为单位)*/

)

/*

创建表变量,表结构与临时表基本一样

就是多了两列,

列ids(自增编号列),

列file_path,存放文件的路径

*/

declare @tem table(

ids smallint identity, /*自增编号列*/

LogicalName nvarchar(128),

PhysicalName nvarchar(260),

File_path nvarchar(260),

Type char(1),

FileGroupName nvarchar(128)

)

insert into #tem

execute('restore filelistonly from disk='''+@filename+'''')

/*将临时表导入表变量中,并且计算出相应得路径*/

insert into @tem(LogicalName,PhysicalName,File_path,Type,FileGroupName)

select LogicalName,PhysicalName,dbo.fn_GetFilePath(PhysicalName),Type,FileGroupName

from #tem

if @@rowcount>0

begin

drop table #tem

end

select @loop_time=1

select @max_ids=max(ids) /*@tem表的ids列最大数*/

from @tem

while @loop_time<=@max_ids

begin

select @file_bak_path=file_path

from @tem where ids=@loop_time

select @sql_cmd='dir '+@file_bak_path

EXEC @proc_result = master..xp_cmdshell @sql_cmd,no_output

/*系统存储过程xp_cmdshell返回代码值:0(成功)或1(失败)*/

IF (@proc_result<>0)

select @loop_time=@loop_time+1

else

BREAK /*没有找到备份前数据文件原有存放路径,退出循环*/

end

select @master_path=''

if @loop_time>@max_ids

select @flag_file=1 /*备份前数据文件原有存放路径存在*/

else

begin

select @flag_file=0 /*备份前数据文件原有存放路径不存在*/

select @master_path=dbo.fn_GetFilePath(filename)

from master..sysdatabases

where name='master'

end

select @sql_sub=''

/*type='d'是数据文件,type='l'是日志文件 */

/*@flag_file=1时新的数据库文件还是存放在原来路径,否则存放路径和master数据库路径一样*/

select @sql_sub=@sql_sub+'move '''+LogicalName+''' to '''

+case type

when 'd' then case @flag_file

when 1 then File_path

else @master_path

end

when 'l' then case @flag_file

when 1 then File_path

else @master_path

end

end

+case type

when 'd' then @restore_db_name

+'_DATA'

+convert(sysname,ids) /*给文件编号*/

+'.'

+right(PhysicalName,3) /*给文件加入后缀名,mdf or ndf*/

+''','

when 'l' then @restore_db_name

+'_LOG'

+convert(sysname,ids) /*给文件编号*/

+'.'

+right(PhysicalName,3) /*给文件加入后缀名,mdf or ndf*/

+''','

end

from @tem

select @sql='RESTORE DATABASE @db_name FROM DISK=@filename with '

select @sql=@sql+@sql_sub+'replace'

select @par='@db_name nvarchar(128),@filename nvarchar(260)'

/*关闭相关进程,把相应进程状况导入临时表中*/

select identity(int,1,1) ids, spid

into #temp

from master..sysprocesses

where dbid=db_id(@restore_db_name)

if @@rowcount>0 --找到相应进程

begin

select @max_ids=max(ids)

from #temp

select @loop_time=1

while @loop_time<=@max_ids

begin

select @sql_kill='kill '+convert(nvarchar(20),spid)

from #temp

where ids=@loop_time

execute sp_executesql @sql_kill

select @loop_time=@loop_time+1

end

end

drop table #temp

execute sp_executesql @sql,@par,@db_name=@restore_db_name,@filename=@filename

select @flag='ok' /*操作成功*/

end

else

begin

SELECT @flag='file type error' /*参数@filename输入格式错误*/

end

GO

--run

--备份数据库test_database

declare @fl varchar(10)

execute pr_backup_db @fl out,'test_database','c:/test_database.bak'

select @fl

--恢复数据库,输入的参数错误

declare @fl varchar(20)

exec pr_restore_db @fl out,'sa','c:/'

select @fl

--恢复数据库,即创建数据库test_database的复本test_db

declare @fl varchar(20)

exec pr_restore_db @fl out,'test_db','c:/test_database.bak'

select @fl

以上过程和函数在MS SQL2000运行成功,由于MS SQL7不支持用户自定义函数和表变量,要在MS SQL7下使用可以把函数fn_GetFilePath改写成过

程,把过程pr_restore_db中的表变量改写为临时表即可运行,有兴趣的朋友可以试试!

1.数据备份:

Close All

Clear

mypath_old=Sys(5)+Sys(2003)

mypath_new=Alltrim(Alltrim(mypath_old)+'/MYDBCBF')

If !Directory("&MYPATH_new.")

Md &mypath_new.

Endif

Set Default To &mypath_new.

mydbf_old=Getfile('bak','','',1,'请输入或选定备份文件名')

If Len(mydbf_old)=0

=Messagebox('你刚才没有录入任何文件名,备份没有成功!!',32,'提示信息')

Set Default To &mypath_old.

Else

mydbf_path=Left(mydbf_old,At('/',mydbf_old,Occurs('/',mydbf_old))-1)

If !Directory("&MYDBF_path.")

Md &mydbf_path.

ENDIF

ERASE &MYDBF_old.

handle=SQLExec(con,"backup database mydbc to disk=?MYDBF_old")

Set Default To &mypath_old.

If handle>0

=Messagebox('(^_^)数据成功备份到【 '+mydbf_path+' 】文件夹下! ',64,'数据库备份')

Else

=Messagebox(Message(),16,'数据库备份')

Endif

Endif

二.恢复:

Close All

Clear

mypath_old=Sys(5)+Sys(2003)

mypath_new=Alltrim(Alltrim(mypath_old)+'/MYDBCBF')

Set Default To &mypath_new.

mydbf=Getfile('bak','','',1,'请选定要恢复的文件名')

Restore From mypath_old+'/myurl/url' Additive

sql_server=Alltrim(my_server)

sql_path=Alltrim(Right(sql_server,Len(sql_server)-Atc('/',sql_server)))

If Len(sql_path)=0

sql_restore_mdf='C:/Program Files/Microsoft SQL Server/MSSQL/Data/mydbc.MDF'

sql_restore_ldf='C:/Program Files/Microsoft SQL Server/MSSQL/Data/mydbc_log.ldf'

Else

sql_restore_mdf='C:/Program Files/Microsoft SQL Server/MSSQL$'+sql_path+'/Data/mydbc.MDF'

sql_restore_ldf='C:/Program Files/Microsoft SQL Server/MSSQL$'+sql_path+'/Data/mydbc_log.ldf'

Endif

*now_timer=1

Try

=SQLDisconnect(con)

Catch

Finally

Endtry

=SQLSetprop(0,"displogin",3) &&永不显示信任连接提示

myurl="driver=sql server;server="+Alltrim(my_server)+;

";uid=sa;pwd="+Alltrim(my_pwd)+;

";database=MASTER"

con_master=Sqlstringconnect(myurl)

If con_master<0

=Messagebox('<@_@>本机已与服务器失去连接,您将退出本系统!',16,'系统信息')

Else

handle=SQLExec(con_master,"RESTORE DATABASE mydbc FROM DISK=?MYDBF With Replace;

,Move 'MYDBC_DATA' To ?SQL_RESTORE_mdf';

,Move 'MYDBC_LOG' To ?SQL_RESTORE_LDF'")

If handle>0

=MESSAGEBOX('^_^数据恢复成功!',32,'数据恢复')

Try

=SQLDisconnect(con_master)

Catch

Finally

Endtry

=SQLSetprop(0,"displogin",3) &&永不显示信任连接提示

myurl="driver=sql server;server="+Alltrim(my_server)+;

";uid=sa;pwd="+Alltrim(my_pwd)+;

";database=mydbc"

con=Sqlstringconnect(myurl)

If con<0

=Messagebox('<@_@>本机已与服务器失去连接,您将退出本系统!',16,'系统信息')

Else

now_timer=0

Endif

Else

=Messagebox(Message(),16,'数据恢复')

Endif

Endif

Set Default To &mypath_old.

数据备份不用多作解释.对于数据恢复:

1.要注意在选定恢复文件时可能会改变当前路径.要在恢复数据后还原当前路径.

2.测试与数据源的连接.因为SQL2000的数据库MASTER等是自带的,只要测试能否连接上其中一个就行.

因为在恢复时可能找不到你要恢复的自定义数据库,所以要测试SQL2000的数据表.

3.SQL2000的安装可能有自定义实例这个也要考虑.比方说你的服务实例名是SERVER那SQL2000生成的文件夹是:MSSQL$SERVER而不是MSSQL

4.在恢复数据时要断开与当前数据库的连接(与上面所述,用SQL2000的自带数据库作为当前连接),否则会产生异常.

5.数据恢复成功后,要恢复与自定义数据库的连接.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: