Sql server 还原问题!!!!!(100分)

  • 主题发起人 主题发起人 hmghj1215
  • 开始时间 开始时间
H

hmghj1215

Unregistered / Unconfirmed
GUEST, unregistred user!
我想在DELPHI 中进行还原操作,可是示“数据库正在使用,所以没有获得数据的排它访问权”,但是要是停止SQL SERVER又提示错误,请问各位这个部题怎么处理?我是个菜鸟,希望能给出具体代码!!!!
 
1、首先要保证所有的用户均已经断开了与数据库的连接,包括查询分析器
2、检查程序的连接在设计状态的connected属性是不是处于true,如是改为false
3、在执行备份语句前,使用写上语句
ADOConnection.connected:=False;
4、在还原语句上加上参数 with replace

由于还原操作还涉及到数据库名有没有存在,同名文件有没有存在等原因,因此并不能保证还原操作一定能成功。(即使程序提示还原操作成功,但有时实际还是没有还原)
 
可是具体的代码怎么写呢?请我指教!!
 
晚上太晚了,明天告诉你
 
levi兄这么说恐怕要把楼主吓到了,万一楼主知难而退岂不罪过啊,呵呵。
SQL数据库还原要注意这几个问题:
1、权限
如果不知道什么权限能还原数据库,请先用sa调试通过;
2、独占
如同删除文件一样,如果有连接正在使用你要欢迎的数据库,你是无法进行还原的,就象你用word打开了一个文档,你能删除它吗?即使是你‘正在进行还原操作的’这个连接,也不能use在该数据库上。解决办法是,首先保证所有use了该数据库的连接(包括查询分析器、你写的各个程序、别人写的各个程序)全部都断开或者use到别的数据库,然后在你执行load指令(或restore)之前,也先执行一下use master;
一般你注意了前面这两点,就足够了;
3、版本
如果备份和还原的数据库版本不同,或者你从另外一台机器的数据库备份来的文件,在还原的时候可能会失败的,遇到这种情况在load语句后加with replace,如load database xxdb from disk = 'path:/db.dmp' with replace
4、多次覆盖问题
如果你在备份时指向了同一个文件,也就是说两次dump出来的文件都是同一个文件名,那么sqlserver是把后一次备份接在前一次备份的后面的!这个比较变态,按照一般的想法直接覆盖就完了。解决办法我没有仔细查过,以前都是在备份时对文件名进行一些处理保证文件名不同,呵呵。我想要么在dump的时候有选项可以选择覆盖式备份,要么在还原时可以指定参数选择一次备份来还原,请levi兄看看有没有解决办法。
 
网址大全:http://16311.855.com/ 在這裡你可以找你想要的網站,你可以把它設置首頁和加入收藏啊!
 
如果你是用Delphi写代码来恢复,请注意将ConnectionString里的数据库段指向master,否则只要你连接过数据库,即使设置Connected为False也没用的。
 
先把正在使用的连接字符串停止然后在用另一个字符串进行恢复~!
 
这是直接从我的代码从拷出来的,供参考
Function DataBaseExist(AdoSqlConn:TAdoConnection; ServerName,UserID,PassWord,DbName:String):Boolean;
var tpQuery:TAdoQuery;
begin
Result:=False;
try
tpQuery:=TAdoQuery.Create(nil);
with tpQuery do
begin
Connection:=AdoSqlConn;
Sql.Add('select Count(Name) from Master..SysDataBases Where Name='''+dbName+'''');
Open;
Result:=Fields[0].AsInteger=1;
Close;
end;
Finally
tpQuery.Free;
end
end;
以上是用来判断数据库名称是不是存在的,在恢复之前最好验证一下

Function RestoreDataBase(ADOSqlConn:TAdoConnection; DbName, BackupFilePos:String):Boolean;
Function CheckFileUsing(ADOSqlConn:TAdoConnection; DbName, BackupFilePos:String):Boolean;
Function GetFileName(FullFileName:String):String;
var tpStr:String; //这个就是从一个含有路径的字符串中取出文件名,由于调用了其他函数,所以你可能不能直接使用
I:Integer;
begin
tpStr:=trim(GetAppointStr('/',FullFileName,CountStrTimes('/',FullFileName)));
tpStr:=GetAppointStr('.',tpStr,1);
Result:=trim(tpStr);
end;
var TpQuery:TAdoQuery;
NewDb,NewFile:String;
begin
Result:=False;
try
NewDb:=GetFileName(BackUpFilePos);
tpQuery:=TAdoQuery.Create(nil);
with tpQuery do
begin
Connection:=AdoSqlConn;
Sql.Add('select Name,FileName from Master..SysDataBases Where Name<>'''+DBName+'''');
Open;
while Not Eof do
if StrIsSame(NewDb,GetFIleName(FieldByName('FileName').AsString)) then
begin
ShowMsg('数据库<'+trim(FieldByName('Name').AsString)+'>正在使用文件名<'+NewDb+'.mdf>,恢复操作无法继续!');
Result:=True;
Break;
Exit;
end
else
Next;
end;
Finally
tpQuery.Close;
tpQuery.Free;
end;
end;
var
tpStr:TStrings;
begin
if StrisEmpty(DbName) or StrIsEmpty(BackUpFilePos) then
begin
ShowMsg('数据库名称或置份文件位置未指定!');
Exit;
end;
if Not DbFileExist(ADOSqlConn,BackUpFilePos) then
begin
ShowMsg('指定的备份文件不存在,请确认!');
Exit;
end;
if CheckFileUsing(ADOSqlConn,DbName,BackupFilePos) then
Exit;
try
tpStr:=TStringList.Create;
tpStr.add('use [Master]');
tpStr.add('');
tpStr.Add('Restore DataBase');
tpStr.Add(' ['+trim(DbName)+'] ');
tpStr.Add(format('FROM DISK = N''%s''',[BackupFilePos]));
TPsTR.Add('WITH RECOVERY , REPLACE');
tpStr.add('');
tpStr.Add('use ['+DbName+']');
try
if AdoSqlConn.Connected then
AdoSqlConn.Connected:=False;
if AskBox('由于恢复操作具有较大危险性,作者不承担由此造成的任何损失!'+#10+
'请在执行恢复前中断数据库服务器与所有用户的连接!'+#10+
'请再次确认是否执行恢复操作?') then
begin
ADOSqlConn.Execute(tpStr.text);
Result:=True;
end
else
Result:=False;
except
on ErrType:Exception do begin
ShowMsg(ErrType.Message);
Result:=False;
Abort;
end;
end;
finally
tpStr.Free;
end;
end;

另外,有关Wolfding兄讲的备份时数据接在原备份后面的问题,如果在企业管理器上操作,则选中 “重写原备份文件选项即可”
如果是用程序备份,则使用下面的语句即可
'Backup DataBase 数据库名 TO '+
Format('DISK = N''%s'' WITH INIT,',[SavePos]))
即加上with init选项,默认是with noinit的,即追加的

如果你不想自己写,可以参考我编的一个小工具
http://feelfinfn.www72.cn4e.com
(绝没有发布广告之意,不要拍我砖头)
 
原来with init是做这个用途的。。。怪不得别人改代码的时候加了这一条,^_^
 
请问levi,你的代码我修改,为什么恢复不了数据库,请望多指教!我的代码如下:
var
Str : String;
tpStr : TStrings;
begin
if YesAndNoDlg('恢复前要关闭所有窗口,是否继续?') = 7 then Exit;
Data.ADOC1.Close;
OpenDlg.InitialDir := ExePath+BACKUP_DIR;
if OpenDlg.Execute then str := OpenDlg.FileName ;
if Trim(Str) <> '' then
begin
try
tpStr:=TStringList.Create;
tpStr.add('use [Master]');
tpStr.add('');
tpStr.Add('Restore DataBase');
tpStr.Add(' [HTDZS] ');
tpStr.Add(format('FROM DISK = N''%s''',[Str]));
TPsTR.Add('WITH RECOVERY , REPLACE');
tpStr.add('');
tpStr.Add('use [HTDZS]');
try
if Data.ReAdoc.Connected then
Data.ReAdoc.Connected:=False;
if YesAndNoDlg('由于恢复操作具有较大危险性,作者不承担'+#10+'由此造成的任何损失!请在执行恢复前中断'+#10+
'数据库服务器与所有用户的连接!请再次确'+#10+
'认是否执行恢复操作?') = 6 then
begin
Data.ReAdoc.Execute(tpStr.text);
OkDlg('数据库恢复完毕!');
end;
except
OkDlg('恢复数据库时出错,请重试!');
end;
Finally
tpStr.Free;
end;
end;
 
提示什么错误?
同时请注意是否存在以下几种情况:
1、比如说原来数据库是 abc,备份文件是 abc.bak,然后现在新建了 xyz数据库,用 abc.bak的备份,由于此时abc数据库还存在,相应的文件名为 abc.mdf, 但xyz的数据库用abc.bak恢复时,默认的文件名也是 abc.mdf的,由于ADO是不报这种错误的,表面上看,升级成功了,但实际还是没恢复。像这种情况,你用同样的操作到企业管理器或者查询分析器下试试看就可以了
2、可能数据库被其他连接占用,这种程序会提示错误,出现这情况的错误应该是你在设计环境下把连接的connected=True了
 
没有提示错误,表面上看,升级成功了,但实际还是没恢复,也还没有以下的情况:比如说原来数据库是 abc,备份文件是 abc.bak,然后现在新建了 xyz数据库,用 abc.bak的备份,由于此时abc数据库还存在,相应的文件名为 abc.mdf, 但xyz的数据库用abc.bak恢复时,默认的文件名也是 abc.mdf的.这是为什么?
 
以上代码执行不成功,请问那位能说的再清楚一点!!!!
 
晕上面几位哥门是不是搞得太麻烦了点,直接写个存储过程,在里面用SQLSERVER的KILL命令干掉枚举出来的连接进程不就行了吗。。
 
请cailei710能说的清楚一点吗?
 
接受答案了.
 
后退
顶部