Извлечение поля из RESTORE HEADERONLY


12

Я пытаюсь использовать ' RESTORE HEADERONLY ', чтобы получить дату создания резервной копии, которую я собираюсь восстановить.

Команда:

RESTORE HEADERONLY FROM DISK = '<path to .bak file>'

прекрасно работает в Query Analyzer и дает набор результатов с примерно 50 столбцами.

Проблема на самом деле доступ к этому из кода.

Я могу получить это во временной таблице, объявив каждый столбец 50: ish, вставив в него значение execи получив от него желаемое значение.

Проблема в том, что я действительно хочу избежать объявления всего набора результатов как временной таблицы, поскольку это кажется очень хрупким решением, если в будущих версиях к нему будут добавлены столбцы.

Есть ли способ просто получить один столбец из этого набора результатов, не объявляя все столбцы?

Ответы:


12

Это работает для меня.

SELECT BackupStartDate 
FROM OPENROWSET('SQLNCLI',
                'Server=MARTINPC\MSSQL2008;Trusted_Connection=yes;',
'SET NOCOUNT ON;SET FMTONLY OFF;EXEC(''
RESTORE HEADERONLY 
FROM DISK = ''''C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQL2008\MSSQL\Backup\DB1.bak''''
'')'
) 

Параметр специальных распределенных запросов должен быть включен. Или, если вы не хотите этого делать, вы можете установить сервер с обратной связью и использовать его вместо этого.

EXEC sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                        @provider = 'SQLOLEDB', @datasrc = @@servername

SELECT BackupStartDate 
FROM OPENQUERY(LOCALSERVER, 
               'SET FMTONLY OFF;
               EXEC(''
               RESTORE HEADERONLY 
               FROM DISK = ''''C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQL2008\MSSQL\Backup\DB1.bak''''
'')')

Умно, и спасибо за то, что поделились, но только для записи, я думаю, что это так же хрупко / сложно, как и большой список столбцов в конце. Жаль, что нет элегантного решения.
Тим Абелл

@TimAbell - Да, я не думаю, что на самом деле я бы использовал это на практике, за исключением, может быть, для получения определения таблицы в первую очередь.
Мартин Смит

1
Я не мог заставить любой запрос работать. Кто-нибудь еще получает сообщение об ошибке «Метаданные не могут быть определены, потому что оператор RESTORE HEADERONLY ... не поддерживает обнаружение метаданных»? Я верю, что sp_describe_first_result_setсистема sp является виновником. Я также поднял этот вопрос в качестве отдельного билета здесь
Stackoverflowuser

@Stackoverflowuser - похоже, что я изначально проверял это на экземпляре 2008 года (из MARTINPC\MSSQL2008), поэтому, возможно, что-то изменилось в более поздних версиях, что означает, что это больше не работает.
Мартин Смит

1
@Stackoverflowuser, приведенный выше пример работает, когда сервер @@ version <2012. Начиная с 2012 года, вместо выполнения этого запроса, вы можете увидеть в Profiler этот: exec [sys] .sp_describe_first_result_set N'SET FMTONLY OFF; EXEC ('' Восстановить заголовок только с диска = '' '' C: \ Program Files \ Microsoft SQL Server \ MSSQL10.MSSQL2008 \ MSSQL \ Backup \ DB1.bak '' '' '') ', NULL, 1
sepupic

7

Это независимый от версии sp я написал, чтобы получить дату резервного копирования из файла.

Он протестирован для SQL 2008R2, 2012 и 2014.

IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'spGetBackupDateFromFile')
    EXEC ('CREATE PROC dbo.spGetBackupDateFromFile AS SELECT ''stub version, to be replaced''')
GO
/*----------------------------------------------------------------------
                    spGetBackupDateFromFile
------------------------------------------------------------------------
Versie      : 1.0
Autheur     : Theo Ekelmans 
Datum       : 2016-03-31
Change      : Initial release 
------------------------------------------------------------------------*/
alter procedure dbo.spGetBackupDateFromFile(@BackupFile as varchar(1000), @DT as datetime output) as 

declare @BackupDT datetime
declare @sql varchar(8000)
declare @ProductVersion NVARCHAR(128)
declare @ProductVersionNumber TINYINT

SET @ProductVersion = CONVERT(NVARCHAR(128),SERVERPROPERTY('ProductVersion'))
SET @ProductVersionNumber = SUBSTRING(@ProductVersion, 1, (CHARINDEX('.', @ProductVersion) - 1))

if object_id('dbo.tblBackupHeader') is not null drop table dbo.tblBackupHeader

set @sql = ''

-- THIS IS GENERIC FOR SQL SERVER 2008R2, 2012 and 2014
if @ProductVersionNumber in(10, 11, 12)
set @sql = @sql +'
create table dbo.tblBackupHeader
( 
    BackupName varchar(256),
    BackupDescription varchar(256),
    BackupType varchar(256),        
    ExpirationDate varchar(256),
    Compressed varchar(256),
    Position varchar(256),
    DeviceType varchar(256),        
    UserName varchar(256),
    ServerName varchar(256),
    DatabaseName varchar(256),
    DatabaseVersion varchar(256),        
    DatabaseCreationDate varchar(256),
    BackupSize varchar(256),
    FirstLSN varchar(256),
    LastLSN varchar(256),        
    CheckpointLSN varchar(256),
    DatabaseBackupLSN varchar(256),
    BackupStartDate varchar(256),
    BackupFinishDate varchar(256),        
    SortOrder varchar(256),
    CodePage varchar(256),
    UnicodeLocaleId varchar(256),
    UnicodeComparisonStyle varchar(256),        
    CompatibilityLevel varchar(256),
    SoftwareVendorId varchar(256),
    SoftwareVersionMajor varchar(256),        
    SoftwareVersionMinor varchar(256),
    SoftwareVersionBuild varchar(256),
    MachineName varchar(256),
    Flags varchar(256),        
    BindingID varchar(256),
    RecoveryForkID varchar(256),
    Collation varchar(256),
    FamilyGUID varchar(256),        
    HasBulkLoggedData varchar(256),
    IsSnapshot varchar(256),
    IsReadOnly varchar(256),
    IsSingleUser varchar(256),        
    HasBackupChecksums varchar(256),
    IsDamaged varchar(256),
    BeginsLogChain varchar(256),
    HasIncompleteMetaData varchar(256),        
    IsForceOffline varchar(256),
    IsCopyOnly varchar(256),
    FirstRecoveryForkID varchar(256),
    ForkPointLSN varchar(256),        
    RecoveryModel varchar(256),
    DifferentialBaseLSN varchar(256),
    DifferentialBaseGUID varchar(256),        
    BackupTypeDescription varchar(256),
    BackupSetGUID varchar(256),
    CompressedBackupSize varchar(256),'

-- THIS IS SPECIFIC TO SQL SERVER 2012
if @ProductVersionNumber in(11)
set @sql = @sql +'
    Containment varchar(256),'


-- THIS IS SPECIFIC TO SQL SERVER 2014
if @ProductVersionNumber in(12)
set @sql = @sql +'
    Containment tinyint, 
    KeyAlgorithm nvarchar(32), 
    EncryptorThumbprint varbinary(20), 
    EncryptorType nvarchar(32),'


--All versions (This field added to retain order by)
set @sql = @sql +'
    Seq int NOT NULL identity(1,1)
); 
'
exec (@sql)


set @sql = 'restore headeronly from disk = '''+ @BackupFile +'''' 

insert into dbo.tblBackupHeader 
exec(@sql)

select @DT = BackupStartDate from dbo.tblBackupHeader 

if object_id('dbo.tblBackupHeader') is not null drop table dbo.tblBackupHeader

1
Согласно stackoverflow.com/a/31318785/489865 и support.microsoft.com/en-us/kb/3058865 , KeyAlgorithm / EncryptorThumbprint / EncryptorType, который вы добавили для «SQL SERVER 2014», фактически появился только в SP1. Я считаю, что версия Build для этого есть 12.0.4100.1, поэтому код должен смотреть на все поля, SERVERPROPERTY('ProductVersion')чтобы правильно учесть это.
JonBrave

7

Поскольку вы спрашивали только о доступе к данным из «кода» без указания каких-либо подробностей о типе кода, я представляю решение PowerShell :

Invoke-SQLcmd -Query "RESTORE HEADERONLY FROM DISK = 'R:\SQLFiles\MSSQL.MSSQLSERVER.Backup\Backup.bak'" | Select-Object MachineName,DatabaseName,HasBackupChecksums,BackupStartDate,BackupFinishDate

1
Это даже лучше, так как мы можем сделать что-то вроде `ls | % {$ _. полное имя} | % {invoke-sqlcmd -Query "RESTORE HEADERONLY FROM DISK = '$ _'"} | формат таблицы `
Луис Фелипе

6

Старомодный способ, для справки:

declare @backupFile varchar(max) = 'C:\backupfile.bak';
declare @dbName varchar(256);

-- THIS IS SPECIFIC TO SQL SERVER 2012
--
declare @headers table 
( 
    BackupName varchar(256),
    BackupDescription varchar(256),
    BackupType varchar(256),        
    ExpirationDate varchar(256),
    Compressed varchar(256),
    Position varchar(256),
    DeviceType varchar(256),        
    UserName varchar(256),
    ServerName varchar(256),
    DatabaseName varchar(256),
    DatabaseVersion varchar(256),        
    DatabaseCreationDate varchar(256),
    BackupSize varchar(256),
    FirstLSN varchar(256),
    LastLSN varchar(256),        
    CheckpointLSN varchar(256),
    DatabaseBackupLSN varchar(256),
    BackupStartDate varchar(256),
    BackupFinishDate varchar(256),        
    SortOrder varchar(256),
    CodePage varchar(256),
    UnicodeLocaleId varchar(256),
    UnicodeComparisonStyle varchar(256),        
    CompatibilityLevel varchar(256),
    SoftwareVendorId varchar(256),
    SoftwareVersionMajor varchar(256),        
    SoftwareVersionMinor varchar(256),
    SoftwareVersionBuild varchar(256),
    MachineName varchar(256),
    Flags varchar(256),        
    BindingID varchar(256),
    RecoveryForkID varchar(256),
    Collation varchar(256),
    FamilyGUID varchar(256),        
    HasBulkLoggedData varchar(256),
    IsSnapshot varchar(256),
    IsReadOnly varchar(256),
    IsSingleUser varchar(256),        
    HasBackupChecksums varchar(256),
    IsDamaged varchar(256),
    BeginsLogChain varchar(256),
    HasIncompleteMetaData varchar(256),        
    IsForceOffline varchar(256),
    IsCopyOnly varchar(256),
    FirstRecoveryForkID varchar(256),
    ForkPointLSN varchar(256),        
    RecoveryModel varchar(256),
    DifferentialBaseLSN varchar(256),
    DifferentialBaseGUID varchar(256),        
    BackupTypeDescription varchar(256),
    BackupSetGUID varchar(256),
    CompressedBackupSize varchar(256),        
    Containment varchar(256),
    --
    -- This field added to retain order by
    --
    Seq int NOT NULL identity(1,1)
); 

insert into @headers exec('restore headeronly from disk = '''+ @backupFile +'''');
select @dbName = DatabaseName from @headers;
select @dbName;

1
Чтобы это работало в SQL2014, вам понадобятся следующие дополнительные поля в конце таблицы: Containment tinyint, KeyAlgorithm nvarchar (32), EncryptorThumbprint varbinary (20), EncryptorType nvarchar (32)
Майк

Существует также этот ответ , который не использует varchar для всего и включает дополнительные столбцы для SQL Server 2014.
Baodad

Обратите внимание, что эти дополнительные столбцы были добавлены в SQL 2014 SP1 . Я верю, что Build Version для этого есть 12.0.4100.1.
JonBrave
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.