Annonceindlæg fra Conscia
11. december 2006 - 11:50
#4
Hvis jeg i forvejen har lavet en backup af en database, så vil jeg kunne restore den - naturligvis. Programmet skal kun kunne restore - ikke lave backup. Det er ikke en af system-databaserne, bare en vilkårlig en.
11. december 2006 - 13:00
#5
Det kan godt være mig der ikke ved at .BAK er en ekstensionen for backup til én type database - men det ved jeg altså ikke, så kan du ikke fortælle hvilken database der er tale om? De forskellige databaser tilbyder forskellige API'er. En i Interbase/Firebird/MSSql vil man kunne bruge dette, mens jeg har mine tvivl mht. MySQL.
11. december 2006 - 13:11
#7
Jeg har tænkt mig at lave forespørgslen "RESTORE DATABASE ...." via TAdoQuery, men problemet bliver, at jeg skal finde de "originale" navne til .ldf og .mdf-filen, og disse kan jeg finde ved "RESTORE filelistonly ....". Men mit problem bliver derefter at kopiere de to resultater jeg får. Pt. er det min bedste løsning, men hvis I har andre forslag, så er I meget velkomne.
15. januar 2007 - 13:48
#9
Lidt til inspiration unit uReplicationRestore; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TRestoreThread = class(TThread) private FSQL: TStringList; FDestDir: string; FUnKilledDBProcessed: Boolean; FRaiseRestoreException: Boolean; procedure SetDestDir(const Value: string); protected procedure Execute; override; public constructor Create; destructor Destroy; override; property DestDir: string read FDestDir write SetDestDir; property UnKilledDBProcessed : Boolean read FUnKilledDBProcessed; property RaiseRestoreException : Boolean read FRaiseRestoreException write FRaiseRestoreException; end; TFReplicationRestore = class(TForm) Timer1: TTimer; Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormShow(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); private FRestored: Boolean; procedure RestoreThreadTerminateEvent(Sender: TObject); { Private declarations } public { Public declarations } property Restored: Boolean read FRestored; end; var FReplicationRestore: TFReplicationRestore; implementation {$R *.dfm} uses SqlExpr, UnitconnectionPool, UnitDataConnection, UnitTypes, UnitNewApplication, ActiveX; procedure TFReplicationRestore.Button1Click(Sender: TObject); begin Close; end; procedure TFReplicationRestore.FormShow(Sender: TObject); begin Timer1.Enabled := True; end; { TRestoreThread } constructor TRestoreThread.Create; begin inherited Create(True); FreeOnTerminate := True; FSQL := TStringList.Create; Priority := tpLower; FUnKilledDBProcessed := False; FRaiseRestoreException := True; end; destructor TRestoreThread.Destroy; begin FreeAndNil(FSQL); inherited; end; procedure TRestoreThread.Execute; var SQLServerConnection: TSQLServerConnection; SQLQuery: TSQLQuery; KillProcesSQL : TStringList; begin if FDestDir = '' then FDestDir := Application.ExePath + 'DBS\'; KillProcesSQL := TStringList.Create; KillProcesSQL.Add(' declare @spid int'); KillProcesSQL.Add(' declare @kill_str varchar(100)'); KillProcesSQL.Add(' declare proc_cur cursor for'); KillProcesSQL.Add(' select'); KillProcesSQL.Add(' a.spid'); KillProcesSQL.Add(' from'); KillProcesSQL.Add(' master..sysprocesses a(nolock)'); KillProcesSQL.Add(' inner join'); KillProcesSQL.Add(' master..sysdatabases b(nolock)'); KillProcesSQL.Add(' on a.dbid = b.dbid'); KillProcesSQL.Add(' where b.name = ''QQQ'''); KillProcesSQL.Add('open proc_cur'); KillProcesSQL.Add(''); KillProcesSQL.Add('fetch next from proc_cur into @spid'); KillProcesSQL.Add('while @@fetch_status=0'); KillProcesSQL.Add('begin'); KillProcesSQL.Add(' print ''killed: '' + convert(varchar, @spid)'); KillProcesSQL.Add(' set @kill_str = ''kill '' + convert(varchar, @spid)'); KillProcesSQL.Add(' exec(@kill_str)'); KillProcesSQL.Add(' fetch next from proc_cur into @spid'); KillProcesSQL.Add('end'); KillProcesSQL.Add(''); KillProcesSQL.Add('deallocate proc_cur'); FSQL.Add('RESTORE DATABASE [QQQ]'); FSQL.Add('FROM DISK = N''@@DbPath@@full.bak'' WITH FILE = 1, NOUNLOAD ,'); FSQL.Add('STATS = 10, REPLACE , RECOVERY, '); FSQL.Add('MOVE N''DBBO_DATA'' TO N''@@DbPath@@QQQ_DATA.MDF'','); FSQL.Add('MOVE N''DBBO_LOG'' TO N''@@DbPath@@QQQ_log.LDF'''); coInitialize(nil); SQLServerConnection := TSQLServerConnection.Create(nil); try SQLServerConnection.DatabaseName := 'Master'; SQLQuery := TSQLQuery.Create(nil); SQLQuery.SQLConnection := SQLServerConnection; if ConnectionPool.UseDBBO1 then SQLQuery.SQL.Text := StringReplace(KillProcesSQL.Text, 'QQQ', 'DBBO', [rfReplaceAll, rfIgnoreCase]) else SQLQuery.SQL.Text := StringReplace(KillProcesSQL.Text, 'QQQ', 'DBBO1', [rfReplaceAll, rfIgnoreCase]); try SQLServerConnection.Open; SQLQuery.ExecSQL(True); Except FUnKilledDBProcessed := True; end; if not(FUnKilledDBProcessed) then begin if ConnectionPool.UseDBBO1 then SQLQuery.SQL.Text := StringReplace(FSQL.Text, 'QQQ', 'DBBO', [rfReplaceAll, rfIgnoreCase]) else SQLQuery.SQL.Text := StringReplace(FSQL.Text, 'QQQ', 'DBBO1', [rfReplaceAll, rfIgnoreCase]); SQLQuery.SQL.Text := StringReplace(SQLQuery.SQL.Text, '@@DbPath@@', FDestDir, [rfReplaceAll, rfIgnoreCase]); try SQLQuery.ExecSQL(True); except on E: Exception do begin if FRaiseRestoreException then raise Exception.Create('Database restore error:' + E.Message); end; end; end; finally FreeAndNil(SQLQuery); FreeAndNil(SQLServerConnection); FreeAndNil(KillProcesSQL); coUnInitialize; end; end; procedure TFReplicationRestore.RestoreThreadTerminateEvent(Sender: TObject); begin FRestored := True; ConnectionPool.ChangeDatabase; end; procedure TFReplicationRestore.Timer1Timer(Sender: TObject); begin Timer1.Enabled := False; FRestored := True; ConnectionPool.ChangeDatabase; Button1.Click; end; procedure TRestoreThread.SetDestDir(const Value: string); begin FDestDir := IncludeTrailingPathDelimiter(Value); end; procedure TFReplicationRestore.FormCreate(Sender: TObject); begin AlphaBlendValue := 0; AlphaBlend := True; FRestored := False; end; end.