簡體   English   中英

從數據庫備份文件還原的SQL Server存儲過程

[英]SQL Server stored procedure to Restore from Database backup file

我在SQL Server中有一個存儲過程,旨在從其他服務器創建的備份文件中還原數據庫。 它動態構造語句以從磁盤上的備份文件還原,在數據庫中創建一個新用戶(因為它正在還原到另一台服務器),以兩種不同的模式授權該用戶,將該用戶分配給兩個單獨的角色,然后刪除舊用戶(來自另一台服務器上的舊數據庫)。

存儲過程代碼在下面(很長一段時間),但是我可以對其進行測試,我添加了一個標志參數( @exec bit = 0 )來控制它是否實際執行所生成的SQL語句,或者只是將其打印出來。 如果傳遞@exec = 1,它將執行SQL,但是如果不傳遞,它將只打印它們,因此我可以分別運行它們以測試動態SQL代碼生成。 由於存儲過程代碼調用restore,並且您無法還原當前數據庫,因此必須從同一服務器上的另一個數據庫中運行它,但是在存儲過程中,在執行Restore ,它將當前數據庫切換到新還原的數據庫。數據庫執行剩余的SQL語句。 它構造的SQL語句如下:

Restore Database [newDBName]
from disk = N'\\BTSSqlTest1\lien_refreshes\BackUps\LASDB.1.31s100.bak'  
with File = 1,
move N'lasdb' to N'E:\lien_refreshes\SQLData\newDBName.mdf',
move N'lasdb_log' to N'E:\lien_refreshes\SQLData\newDBName.ldf',
NoUnload, Replace, Stats = 25;


Use [newDBName]

Create User [domain\NewUserName]

Grant execute to [domain\NewUserName]

Alter Authorization On Schema::[db_backupoperator] to [domain\NewUserName]

Alter Authorization On Schema::[db_Owner] to [domain\NewUserName]

sp_AddRolemember 'db_backupoperator', domain\NewUserName'

sp_AddRolemember 'db_owner', domain\NewUserName'

sp_DropUser [domain\OldUserName]

當我在SQL Server企業管理器中分別運行這些語句時,它們均按設計工作。

當我使用@exec=1運行存儲過程時,它將使用Exec ([SQL])單獨執行每個語句。 但是,盡管除Drop User語句之外的所有內容似乎都已成功完成,這會引發錯誤

用戶在數據庫中不存在

運行存儲過程的結果:

25 percent processed. 
50 percent processed. 
75 percent processed. 
100 percent processed. 
Processed 779144 pages for database 'newDBName', file 'lasdb' on file 1.
Processed 6 pages for database 'newDBName', file 'lasdb_log' on file 1. 
RESTORE DATABASE successfully processed 779150 pages in 11.532 seconds (527.845 MB/sec). 
Database [newDBName] restored. 
Switched to Database [newDBName]. 
Execute granted to user [domain\NewUserName]. 
User [domain\NewUserName] authorized in schema db_backupoperator. 
User [domain\NewUserName] authorized in schema db_Owner. 
User [domain\NewUserName] added to role db_backupoperator. 
User [domain\NewUserName] added to role db_Owner. 
Msg 15008, Level 16, State 1, Procedure sp_dropuser, Line 12 
User domain\OldUserName' does not exist in the current database. 
Dropped User [domain\OldUserName].

當我查看生成的數據庫本身時(即使刷新后),新創建的用戶不在數據庫中,而另一台服務器上的舊用戶仍在該數據庫中。

 ******************************************************
 ****** Stored proc ***********************************
 Create PROCEDURE RestoreProdTest
 @fileSpec nvarchar(400), 
 @exec bit = 0
 As
 Set NoCount On
 declare @nl Char(2) = char(13) + char(10)
 declare @2nl char(4) = @nl + @nl
 -- --------------------------------
 declare @debugMsg varchar(max) = 'Variable Values:' + @nl
 declare @sqlCode varchar(max) = 'Executable SQL Code:' + @nl

   declare @dbNm nvarchar(50) = 'newDBName' 
   declare @user varchar(40) = 'domain\NewUserName' 
   declare @dbId int = DB_Id(@dbNm)
   -- ----------------------------------------------------------------
   Declare @tab Table 
          (logNm varchar(256), phyNm varchar(300), 
        Typ varchar, FilGrpNm varChar(128), Siz varchar(128), 
           MaxSize varChar(128), FileId varchar(128), 
           CreateLSN varChar(128), 
           DropLSN varchar(128), UniqueId varChar(128), 
           ROLSN varchar(128), 
           RWLSN varchar(128), BkSizBytes varChar(128), 
           SrceBlckSize varchar(128), 
           FileGrpId varchar(128), LogGrpId varChar(128), 
           DiffBaseLSN varchar(128), 
           DiffBaseGUID varchar(128), IsReadOnly varChar(128), 
           IsPresent varchar(128), ThumbPrint varchar(128)) 
   -- ----------------------------------------------------------
   Insert @tab(logNm, phyNm, Typ, FilGrpNm, Siz, MaxSize, FileId, 
          CreateLSN, DropLSN, UniqueId, ROLSN, RWLSN, BkSizBytes, 
          SrceBlckSize, FileGrpId, LogGrpId, DiffBaseLSN, 
          DiffBaseGUID, IsReadOnly, IsPresent, ThumbPrint)
   Exec('Restore fileListOnly from disk=''' + @fileSpec + '''')
   declare @oldDataFileSpec varChar(400),
           @oldLogFileSpec  varChar(400)
   Set @oldDataFileSpec = (Select logNm from @tab where Typ = 'D')
   Set @oldLogFileSpec  = (Select logNm from @tab where Typ = 'L')
   -- -------------------------------------
   declare @dataFile varChar(400)
   declare @logFile varChar(400)
   Select @dataFile = physical_name
   from sys.Master_Files 
   Where Database_Id = @dbId and type = 0
   Select @logFile = physical_name
   from sys.Master_Files
   Where Database_Id = @dbId and type = 1

   declare @killSql nVarChar(200) = 'msdb.dbo.sp_KillUserProc '  

   declare @restoreSql nVarChar(1000) = 
          N'Restore Database [' + @dbNm + ']' + @nl + 
          'from disk = N''' + @fileSpec + ''' with File = 1,' + @nl +
          '   move N''' + @oldDataFileSpec + '''' + ' to N''' + 
              @dataFile + ''',' + @nl +
          '   move N''' + @oldLogFileSpec  + '''' + ' to N'''  + 
              @logFile + ''',' + @nl +
          '   NoUnload, Replace, Stats = 25;'


   declare @spids table (spid integer primary key not null)
   insert @spids(spid)
   select session_id from sys.dm_exec_sessions
   where database_id = @dbId
   -- ----------------------
   declare @spid int = 0
   declare @spidstr varchar(4)
   while exists (select * from @spids where spid > @spid) begin
          Select @spid = min(spid) from @spids where spid > @spid
          set @spidstr = format(@spid, '0')
          set @sqlCode += @killSql + @spidstr + @nl
   end
   -- --------------------------------------------

   if @exec = 1 Begin 
          Set @spid = 0
          while exists (select * from @spids where spid > @spid) begin
                 Select @spid = min(spid) from @spids where spid > @spid
                 set @spidstr = format(@spid, '0')
                 exec(@killSql + @spidstr)
          end
          -- ------------------------------------------------
          exec (@restoreSql)
          print ' Database [' + @dbNm + '] restored.'
   end
   else Set @sqlCode += @restoreSql + @2nl 

   -- Switch to new restored database
   declare @UseSql nVarChar(100) = 'Use [' + @dbNm + ']'
   if @exec = 1 begin
          exec (@UseSql) 
          print 'Switched to Database [' + @dbNm + '].'
   end else Set @sqlCode += @UseSql + @2nl

   -- Grant execute permissions (also creates the user)
   declare @grantSql nVarChar(1000) = N'Grant execute to [{User}]'
   Set @grantSql = Replace(@grantSql, '{User}', @user)
   if @exec = 1  begin
          exec (@grantSql) 
          print 'Execute granted to user [' + @user + '].'
   end else Set @sqlCode += @grantSql + @2nl

   -- Assign user to schemas -------------
   declare @schmSql nVarChar(200) = 
          N'Alter Authorization On Schema::[db_backupoperator] to [{user}]'
   Set @schmSql = Replace(@schmSql, '{User}', @user)
   if @exec = 1 begin
          exec (@schmSql) 
          print 'User [' + @user + '] authrzd in schema db_backupoperator.'
   end else Set @sqlCode += @schmSql + @2nl
   -- ----------------------------
   Set @schmSql = Replace(@schmSql, 'db_backupoperator', 'db_Owner')
   if @exec = 1 begin
          exec (@schmSql) 
          print 'User [' + @user + '] authorized in schema db_Owner.'
   end else Set @sqlCode += @schmSql + @2nl
   -- --------------------------------------------------

   -- Grant backup operator & dbOwner Roles 
   declare @roleSql nVarChar(1000) = 
          'sp_AddRolemember ''db_backupoperator'', ''{User}''' 
   Set @roleSql = Replace(@roleSql, '{User}', @user)
   if @exec = 1 begin
          exec (@roleSql) 
          print 'User [' + @user + '] added to role db_backupoperator.'
   end else Set @sqlCode += @roleSql + @2nl
   -- ---------------------------
   set @roleSql = 'sp_AddRolemember ''db_owner'', ''{User}''' 
   Set @roleSql = Replace(@roleSql, '{User}', @user)
   if @exec = 1 begin
          exec (@roleSql) 
          print 'User [' + @user + '] added to role db_Owner.'
   end else Set @sqlCode += @roleSql + @2nl

   -- ----- Drop PROD User -----------
   declare @dropUserSql nVarchar(50) = 
          'sp_DropUser [rose\LasPROD_Svc]' 
   if @exec = 1 begin
          exec (@dropUserSql) 
          print 'Dropped User [rose\LasPROD_Svc].'
   end else Set @sqlCode += @dropUserSql + @2nl
   -- ---------------------------
   if @exec = 0 print @sqlCode
   Return 0

每個EXEC調用應包括“ USE db_name”。

或者將腳本作為一個大腳本而不是多個腳本運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM