我正在尝试从完整备份 (
.fbk
) 和快速备份 (.qbk
) 恢复数据库。按照这个顺序
USE MASTER
RESTORE DATABASE [" + DB_NAME + "]
FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
声明,数据库卡在恢复状态。
当看到内部异常时,它说
数据库处于正在恢复状态时不允许进行 ALTER DATABASE
ALTER DATABASE 语句失败
当我打开 SSMS 时,它在数据库上显示“正在恢复”。
但是,当我仅尝试完整备份(
.fbk
)选项时,它恢复得很好(在本例中它使用“带恢复”)。
请参阅 WriteFile 方法中的 else if 条件。
private void WriteFile()
{
try
{
// Creates Restore.sql file.
string strTSQLFile = Environment.CurrentDirectory + "\\Restore.sql";
FileInfo File = new FileInfo(strTSQLFile);
StreamWriter Writer = File.CreateText();
// Write open database
string strTemp;
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
Writer.WriteLine("Go");
if (Complete_Opt.Checked == true) // Full restore
{
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH RECOVERY";
Writer.WriteLine(strTemp);
}
else if (Differential_Opt.Checked == true) // Quick restore
{
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("GO");
Writer.WriteLine("WAITFOR DELAY '00:00:10'");
Writer.WriteLine("GO");
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET MULTI_USER");
Writer.WriteLine("GO");
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
Writer.WriteLine("Go");
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + txt_Quick.Text + "\' WITH RECOVERY";
Writer.WriteLine(strTemp);
}
Writer.WriteLine("GO");
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET MULTI_USER");
Writer.WriteLine("GO");
Writer.WriteLine("USE PharmSpecDB");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_TestResults')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_TestResults");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_TestResults ON tblTestResults WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_SampleIDParameter')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_SampleIDParameter");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_SampleIDParameter ON tblSampleIDParameter WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_TestRun')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_TestRun");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_TestRun ON tblTestRun WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ReviewApprove')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_ReviewApprove");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_ReviewApprove ON tblReviewApprove WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ActiveParamValues')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_ActiveParamValues");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_ActiveParamValues ON tblActiveParamValues WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ActivityLogger')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_ActivityLogger");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_ActivityLogger ON tblActivityLogger WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("EXEC sp_revokedbaccess 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_grantdbaccess 'PharmSpecUsr','PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_owner','PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_accessadmin','PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_datareader' ,'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_datawriter ', 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_ddladmin', 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_securityadmin', 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_backupoperator','PharmSpecUsr'");
Writer.WriteLine("GO");
Writer.Close();
}
catch (Exception Exc)
{
throw Exc;
}
}
我正在从 C# 代码执行此 SQL,如下所示:
try
{
string strTSQLFile = Environment.CurrentDirectory + "\\Restore.sql";
if (!File.Exists(strTSQLFile))
{
throw new FileNotFoundException();
}
using (StreamReader srSQL = new StreamReader(strTSQLFile))
{
string sqlLine;
StringBuilder sqlString = new StringBuilder();
while (!srSQL.EndOfStream)
{
sqlLine = srSQL.ReadLine();
if (string.IsNullOrEmpty(sqlLine) == false)
{
// We don't actually execute the "GO" lines but can use them to determine when to call the executenonquery function
if (string.Compare(sqlLine, "GO", true) == 0)
{
// Make sure we have something to execute
if (string.IsNullOrEmpty(sqlString.ToString()) == false)
{
ServerActionResult.ConnectionContext.ExecuteNonQuery(sqlString.ToString());
System.Diagnostics.Debug.WriteLine(sqlString);
}
sqlString.Clear();
}
// Add the next line to the stringbuilder object
else
{
sqlString.AppendLine(sqlLine);
}
}
}
}
}
catch (Exception exc)
{
throw exc;
}
调试:
当说
System.Diagnostics.Debug.WriteLine(sqlString);
时,它会打印:
ALTER DATABASE [PharmSpecDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
USE MASTER RESTORE DATABASE [PharmSpecDB] FROM DISK = 'C:\PharmBackup\Backup\PharmSpecDB_13-Nov-2024-12-42-57-717_Full.Fbk' WITH NORECOVERY
WAITFOR DELAY '00:00:10'
编辑:
通过此评论及其在线内容“要恢复数据库并将其联机以便用户可以连接,您可以使用带有WITH RECOVERY选项的RESTORE DATABASE语句”。我正在尝试这样的事情,
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("Go");
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + txt_Quick.Text + "\' WITH RECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("Go");
这样做就是抱怨,
“日志或差异备份无法恢复,因为没有文件 准备好前滚了。 恢复数据库正在终止 不正常地。 将数据库上下文更改为“主”。”
你尝试过这个吗?
可能是问题的答案,
卡在恢复状态
是...
您需要使用WITH RECOVERY选项,对您的数据库进行RESTORE 命令,作为恢复过程的一部分使您的数据库联机。