我正在运行一个收到错误的脚本。当我注释掉脚本的一部分时,它说它成功了 - 但实际上并没有做任何事情。该脚本是多个目录中多个数据库的还原脚本。该脚本应该将这些数据库还原到与数据库同名的目录中。我将在这里附上脚本:
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
运行时出错:
Msg 213,Level 16,State 7,Line 1 列名或提供的值数与表定义不匹配。 Msg 3013,Level 16,State 1,Line 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
答案 0 :(得分:0)
如果我理解正确,您将在SQL Server 2012服务器上恢复备份。作为文档says,RESTORE HEADERONLY
的结果集中有一个名为containment
的额外列,该列不在SQL 2008中,但您的#bdev
表没有containment
柱。如果您添加它,则RESTORE HEADERONLY
结果将与表格结构匹配。
就个人而言,我会使用外部脚本来代替TSQL。使用外部脚本处理文件更容易,并且所有动态SQL都难以阅读和排除故障。使用PowerShell中的SMO是一个选项,或者只使用您首选的脚本语言来执行TSQL。
答案 1 :(得分:0)
我弄清楚问题是什么......从SQL 2008 R2到SQL 2012,在创建#bdev时还有其他列缺失。
我通过检查两个SQL服务器的表结构来解决了这个问题,并确定在SQL 2012中,他们添加了一个不在我脚本中的新列...添加此列时,脚本工作正常!