0

我正在运行一个出现错误的脚本。当我注释掉脚本的一部分时,它说它成功了——但实际上什么也没做。该脚本是多个目录中多个数据库的还原脚本。该脚本应该将这些数据库恢复到与数据库同名的目录中。我将在此处附上脚本:

   use [master]
GO

set nocount on

declare @curdir nvarchar(400)
declare @line varchar(400)
declare @command varchar(400)
declare @counter bigint
Declare @Database_name varchar(400)
Declare @directory varchar(400)
Declare @filename_name varchar(400)
declare @is_final_restore varchar(1)

set @is_final_restore = 'N'

If (select count (*) from sys.objects where name='Output') <> 0 DROP TABLE output  
If (select count (*) from tempdb.sys.objects where name like '%#Tempoutput%') <> 0 DROP TABLE #Tempoutput   
If (select count (*) from tempdb.sys.objects where name like '%#dirs%') <> 0 DROP TABLE #dirs   

create table #dirs (DIRID bigint identity(1,1), directory varchar(400))
  Set @command = 'dir "E:\MVE_Backups\Full" /S/B/A:A'
 insert into #dirs exec xp_cmdshell @command
  set @counter = (select count(*) from #dirs)
create table #tempoutput (line varchar(400))

create table output (Path_name varchar(400),Directory varchar(400),Files varchar(400),Database_name varchar(400), FileSize varchar(400))
    While @Counter <> 0
      Begin
        Declare @filesize bigint
        set @curdir = (select directory from #dirs where DIRID = @counter)
        set @command = 'dir "' + @curdir +'"'
        insert into #tempoutput
        exec master.dbo.xp_cmdshell @command
           select @line = ltrim(replace(substring(line, charindex(')', line)+1,len(line)), ',', ''))
           from #tempoutput where line like '%File(s)%bytes'
           Set @filesize  = Replace(@line, ' bytes', '')
           Set @filename_name = reverse(left(reverse(@curdir), charindex('\', reverse(@curdir)) -1))
           Set @directory  = reverse(Right(reverse(@curdir), len(@curdir)-charindex('\', reverse(@curdir))))
           Set @Database_name = reverse(left(reverse(@directory), charindex('\', reverse(@directory)) -1))
        Insert into output (Path_name,Directory, Files,Database_name, Filesize) values (@curdir,@directory,@filename_name,@Database_name, @filesize)
        Set @counter = @counter -1
       End
  Delete from output where Path_name is null

DECLARE @fname VARCHAR(200) 
DECLARE @dirfile VARCHAR(300) 
DECLARE @LogicalName NVARCHAR(128) 
DECLARE @PhysicalName NVARCHAR(260) 
DECLARE @type CHAR(1) 
DECLARE @DbName sysname 
DECLARE @sql NVARCHAR(1000) 

  --- Create Temp tables for Restoring


CREATE TABLE #bdev( 
 BackupName NVARCHAR(128) 
,BackupDescription NVARCHAR(255) 
,BackupType smallint 
,ExpirationDate datetime 
,Compressed tinyint 
,Position smallint 
,DeviceType tinyint 
,UserName NVARCHAR(128) 
,ServerName NVARCHAR(128) 
,DatabaseName NVARCHAR(128) 
,DatabaseVersion INT 
,DatabaseCreationDate datetime 
,BackupSize numeric(20,0) 
,FirstLSN numeric(25,0) 
,LastLSN numeric(25,0) 
,CheckpointLSN numeric(25,0) 
,DatabaseBackupLSN numeric(25,0) 
,BackupStartDate datetime 
,BackupFinishDate datetime 
,SortOrder smallint 
,CodePage smallint 
,UnicodeLocaleId INT 
,UnicodeComparisonStyle INT 
,CompatibilityLevel tinyint 
,SoftwareVendorId INT 
,SoftwareVersionMajor INT 
,SoftwareVersionMinor INT 
,SoftwareVersionBuild INT 
,MachineName NVARCHAR(128) 
,Flags INT 
,BindingID uniqueidentifier 
,RecoveryForkID uniqueidentifier 
,Collation NVARCHAR(128) 
,FamilyGUID uniqueidentifier 
,HasBulkLoggedData INT 
,IsSnapshot INT 
,IsReadOnly INT 
,IsSingleUser INT 
,HasBackupChecksums INT 
,IsDamaged INT 
,BegibsLogChain INT 
,HasIncompleteMetaData INT 
,IsForceOffline INT 
,IsCopyOnly INT 
,FirstRecoveryForkID uniqueidentifier 
,ForkPointLSN numeric(25,0) 
,RecoveryModel NVARCHAR(128) 
,DifferentialBaseLSN numeric(25,0) 
,DifferentialBaseGUID uniqueidentifier 
,BackupTypeDescription NVARCHAR(128) 
,BackupSetGUID uniqueidentifier 
,CompressedBackupSize bigint
) 

--Table to hold result from RESTORE FILELISTONLY. Need to generate the MOVE options to the RESTORE command 
CREATE TABLE #dbfiles( 
 LogicalName NVARCHAR(128) 
,PhysicalName NVARCHAR(260) 
,Type CHAR(1) 
,FileGroupName NVARCHAR(128) 
,Size numeric(20,0) 
,MaxSize numeric(20,0) 
,FileId INT 
,CreateLSN numeric(25,0) 
,DropLSN numeric(25,0) 
,UniqueId uniqueidentifier 
,ReadOnlyLSN numeric(25,0) 
,ReadWriteLSN numeric(25,0) 
,BackupSizeInBytes BIGINT 
,SourceBlockSize INT 
,FilegroupId INT 
,LogGroupGUID uniqueidentifier 
,DifferentialBaseLSN numeric(25) 
,DifferentialBaseGUID uniqueidentifier 
,IsReadOnly INT 
,IsPresent INT 
,TDEThumbPrint uniqueidentifier 
) 

DECLARE dbfiles CURSOR FOR 
SELECT LogicalName, PhysicalName, Type FROM #dbfiles 

declare backup_cur cursor for
    select Path_name, Database_name from output 
open backup_cur

fetch next from backup_cur into @filename_name, @database_name

--Loop through each script.
while @@FETCH_STATUS = 0
BEGIN

    if @is_final_restore = 'Y'
    BEGIN
        set @dirfile = @filename_name

        set @Database_name = @Database_name + '_temp'

        print 'RESTORE DATABASE [' + @database_name + '] FROM  DISK = N''' + @dirfile + ''' WITH FILE = 1, NOUNLOAD'
        print 'GO'
        print 'USE [' + @database_name + ']'
        print 'GO'
        print 'sp_changedbowner ''' + @database_name + '_user'''
        print 'GO'
        print 'USE [master]'
        print 'GO'
        print 'ALTER DATABASE [' + @database_name + '] SET TRUSTWORTHY on'
        print 'GO'
        print 'GRANT UNSAFE ASSEMBLY TO [' + @database_name + '_user]'
        print 'GO'
        print 'sp_configure ''clr enabled'', 1'
        print 'GO'
        print 'reconfigure'
        print 'GO'
    END

    ELSE
    BEGIN

        --PRINT ('Now Restoring Database '+ @database_name+' in Non-Recovery Mode. From File :'+@filename_name  )
        set @dirfile = @filename_name
        --Get database name from RESTORE HEADERONLY, assumes there's only one backup on each backup file. 
        TRUNCATE TABLE #bdev 
        INSERT #bdev 
        EXEC('RESTORE HEADERONLY FROM DISK = ''' + @dirfile + '''') 
        SET @DbName = (SELECT DatabaseName FROM #bdev) 

        --Construct the beginning for the RESTORE DATABASE command 
        SET @sql = 'RESTORE DATABASE [' + @DbName + '] FROM DISK = ''' + @dirfile + ''' WITH NORECOVERY, MOVE ' 

        --Get information about database files from backup device into temp table 
        TRUNCATE TABLE #dbfiles 
        INSERT #dbfiles 
        EXEC('RESTORE FILELISTONLY FROM DISK = ''' + @dirfile + '''') 

        OPEN dbfiles 
        FETCH NEXT FROM dbfiles INTO @LogicalName, @PhysicalName, @type 
        --For each database file that the database uses 
        WHILE @@FETCH_STATUS = 0 
        BEGIN 
        IF @type = 'D' 
        SET @sql = @sql + '''' + @LogicalName + ''' TO ''' + 'F:\Database_Files\'+@database_name+'\' + @LogicalName  + '.mdf'', MOVE ' 
        ELSE IF @type = 'L' 
        SET @sql = @sql + '''' + @LogicalName + ''' TO ''' + 'F:\Database_Files\'+@database_name+'\' + @LogicalName + '.ldf''' 
        FETCH NEXT FROM dbfiles INTO @LogicalName, @PhysicalName, @type 
        END 
        PRINT ('EXECUTE master.dbo.xp_create_subdir N'''+'F:\Database_Files\'+@database_name+'''')
        PRINT ('GO')
        PRINT @SQL
        PRINT ('GO')
        close dbfiles
    END
fetch next from backup_cur into @filename_name, @database_name  
END

close backup_cur
deallocate backup_cur
DEALLOCATE dbfiles 

drop table output;

drop table #bdev
drop table #dbfiles

我运行时的错误是:

消息 213,级别 16,状态 7,第 1 行 列名或提供的值的数量与表定义不匹配。消息 3013,级别 16,状态 1,第 1 行 RESTORE HEADERONLY 异常终止。

我注释掉的代码是这样的:

BEGIN
    set @dirfile = @filename_name

    set @Database_name = @Database_name + '_temp'

    print 'RESTORE DATABASE [' + @database_name + '] FROM  DISK = N''' + @dirfile + ''' WITH FILE = 1, NOUNLOAD'
    print 'GO'
    print 'USE [' + @database_name + ']'
    print 'GO'
    print 'sp_changedbowner ''' + @database_name + '_user'''
    print 'GO'
    print 'USE [master]'
    print 'GO'
    print 'ALTER DATABASE [' + @database_name + '] SET TRUSTWORTHY on'
    print 'GO'
    print 'GRANT UNSAFE ASSEMBLY TO [' + @database_name + '_user]'
    print 'GO'
    print 'sp_configure ''clr enabled'', 1'
    print 'GO'
    print 'reconfigure'
    print 'GO'
END

ELSE
4

2 回答 2

0

我弄清楚问题出在哪里......从 SQL 2008 R2 到 SQL 2012,创建#bdev 时缺少额外的列。

我通过检查两个 SQL 服务器的表结构解决了这个问题,并确定在 SQL 2012 中,他们添加了一个不在我的脚本中的新列......添加此列时,脚本运行良好!

于 2013-04-19T13:38:49.373 回答
0

如果我理解正确,您将在 SQL Serve 2012 服务器上恢复备份。正如文档所说,来自的结果集有一个名为SQL 2008 中没有RESTORE HEADERONLY的额外列,但您的表没有列。如果添加它,则结果将与表结构匹配。containment#bdevcontainmentRESTORE HEADERONLY

就个人而言,我会使用外部脚本而不是 TSQL 来执行此操作。使用外部脚本处理文件更容易,而且所有动态 SQL 都难以阅读和排除故障。从 PowerShell使用SMO是一种选择,或者只使用您喜欢的脚本语言来执行 TSQL。

于 2013-04-18T21:03:16.200 回答