尝试使用 Delphi 还原 SQL Server 数据库时"Login failed for user. Cannot open database requested by the login.



我目前正在学习编程,正在尝试新的东西,所以我尝试用程序进行备份和恢复。我最终发现了这一点,并成功地进行了备份和恢复。当我在线程中移动代码时出现了问题。我最终设法解决了备份线程,但我被困在了恢复部分。这是我的恢复线程。

type
TThreadRestoreBackUp = class( TThread )
protected
procedure Execute(); override;
public
DataSource : TMSDataSource;
Connection : TMSConnection;
Query : TMSQuery;
var
DBName, RestorePath, dbRPath, dbRLogPath : string;
differentDB : Boolean;
end;

正如您所看到的,我已经为线程创建了DataSource、Connection和TMSQuery。我这么做是因为我读到在主窗体中使用这些线程是不好的

procedure TfrmCreateBackUp.btnRestoreClick(Sender: TObject);
var
RestoreBackUp : BackUpThread.TThreadRestoreBackUp;
begin
RestoreBackUp := BackUpThread.TThreadRestoreBackUp.Create(True);
RestoreBackUp.FreeOnTerminate := True;
try
RestoreBackUp.DataSource := frmMain.MSDSChanges;
RestoreBackUp.Connection := frmMain.MSConnLyubenAirport;
RestoreBackUp.Query := frmMain.MSQChanges;
RestoreBackUp.DBName := edtDBName.Text;
RestoreBackUp.DifferentDB := tcxCheckBoxNewDB.Checked;
RestoreBackUp.RestorePath := cxbeChoosePath.Text;
RestoreBackUp.Start;
except on EConvertError do
RestoreBackUp.Free;
end;
end;

我给出了连接、数据源和tmsQuery,它们是我主要拥有的数据。此外,我从恢复表单上的组件中获得恢复所需的dbName和不同路径

procedure TThreadRestoreBackUp.Execute();
begin
dbRPath := 'E:ClientDBS';
dbRLogPath := 'E:ClientDBS';
if DifferentDB then
begin
dbRPath := dbRPath + DBName + '.mdf';
dbRLogPath := dbRLogPath + DBName + '.ldf';
Query.SQL.Text := 'If DB_ID(' + QuotedStr(DBName) + ') IS NOT NULL ' +
'USE ' + DBName + ' SELECT * FROM Flights';
Query.Execute;
if Query.IsEmpty then
begin
Query.SQL.Text := 'USE master RESTORE DATABASE ' + DbName +
' FROM DISK = ' + QuotedStr(RestorePath) +
' WITH RECOVERY, MOVE ' + QuotedStr(DBName) +
' TO ' + QuotedStr(dbRPath) + ', MOVE ' + QuotedStr(DBName + '_log') +
' TO ' + QuotedStr(dbRLogPath);
Query.Execute;
end
else
begin
Query.SQL.Text := 'USE master ALTER DATABASE [' + DBName + ']' +
' SET OFFLINE WITH ROLLBACK IMMEDIATE' +
' RESTORE DATABASE ' + DbName +
' FROM DISK = ' + QuotedStr(RestorePath) +
' WITH REPLACE, RECOVERY ' + 'ALTER DATABASE [' + DBName + ']' +
' SET ONLINE';
test := Query.SQL.Text;
Query.Execute;
end;
end
else
begin
DBName := Connection.Database;
Query.SQL.Text := 'USE master ALTER DATABASE [' + DBName +
'] SET OFFLINE WITH ROLLBACK IMMEDIATE' +
' RESTORE DATABASE [' + DBName +
'] FROM DISK = ' + QuotedStr(RestorePath) +
' WITH REPLACE, RECOVERY ALTER DATABASE [' + DBName +
'] SET ONLINE';
test := Query.SQL.Text;
Query.Execute;
end;
Query.SQL.Text := 'USE [' + DBName + ']';
Query.Execute;
DataSource.Free;
Connection.Free;
Query.Free;
end;

代码获取进行恢复所需的路径。我这样做的原因是,我希望用户能够在使用过的同一个数据库中进行恢复,或者在另一个数据库(可能已经存在,也可能不存在(中进行恢复。在获得字符串变量的路径后,我有if语句,它检查表单中不同数据库的框是否被选中。如果是,那么它会继续并尝试使用数据库进行查询,如果查询为空,那么它显然不存在,所以我尝试恢复它,并移动恢复所需的文件,如果它存在,那么它只使用替换进行恢复。很明显,如果不检查不同的数据库,它就会恢复到我使用的数据库中。但问题是;用户登录失败。无法打开登录请求的数据库。登录失败";错误我需要做些什么才能让它再次工作?

如果在目标服务器上手动重新创建了来自备份源的SQL身份验证登录,则可以执行以下操作:

  1. 在目标服务器WITH SID=0x...上重新创建与源上SID匹配的登录名
  2. 恢复数据库后,运行ALTER USER {foo} WITH LOGIN = {bar};将用户重新映射到目标服务器上的登录名

使用Andy Mallon博客文章中的代码可以使其中一些任务变得更容易。很明显,您需要使用还原数据库的帐户,而不是尝试连接的帐户来执行此操作。

相关内容

最新更新