Extrahieren eines Feldes aus RESTORE HEADERONLY


12

Ich versuche, ' HEADERONLY WIEDERHERSTELLEN ' zu verwenden, um das Datum abzurufen , an dem das Backup erstellt wurde, das ich wiederherstellen möchte .

Der Befehl:

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

funktioniert gut in Query Analyzer und gibt eine Ergebnismenge mit etwa 50 Spalten.

Das Problem besteht darin, tatsächlich über Code darauf zuzugreifen.

Ich kann dies in eine temporäre Tabelle aufnehmen, indem ich jede einzelne der 50: ish-Spalten deklariere, mit einfüge execund dort den gewünschten Wert erhalte.

Das Problem ist, dass ich wirklich vermeiden möchte, die gesamte Ergebnismenge als temporäre Tabelle deklarieren zu müssen, da es wie eine sehr spröde Lösung erscheint, wenn sie in zukünftigen Versionen jemals Spalten hinzufügen.

Gibt es eine Möglichkeit, nur eine einzelne Spalte aus dieser Ergebnismenge herauszuholen, ohne alle Spalten zu deklarieren?

Antworten:


12

Das funktioniert bei mir.

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''''
'')'
) 

Die Option für verteilte Ad-hoc-Abfragen muss aktiviert sein. Wenn Sie dies nicht möchten, können Sie einen Loopback-Verbindungsserver einrichten und diesen stattdessen verwenden.

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''''
'')')

Clever und danke fürs Teilen, aber nur für die Aufzeichnung denke ich, dass dies genauso spröde / komplex ist wie die große Liste der Spalten am Ende. Schade, dass es keine elegante Lösung gibt.
Tim Abell

@ TimAbell - Ja, ich glaube nicht, dass ich dies tatsächlich in der Praxis verwenden würde, außer vielleicht, um die Tabellendefinition überhaupt zu erhalten.
Martin Smith

1
Ich konnte keine der beiden Abfragen zum Laufen bringen. Erhält jemand die Fehlermeldung "Die Metadaten konnten nicht ermittelt werden, da die Anweisung HEADERONLY WIEDERHERSTELLEN ... die Metadatenerkennung nicht unterstützt"? Ich glaube, sp_describe_first_result_setSystem SP ist der Schuldige dahinter. Ich habe diese Frage auch als separates Ticket hier gestellt
Stackoverflowuser

@Stackoverflowuser - sieht so aus, als hätte ich dies ursprünglich gegen eine Instanz von 2008 (von MARTINPC\MSSQL2008) getestet. In späteren Versionen hat sich möglicherweise etwas geändert, was bedeutet, dass dies nicht mehr funktioniert.
Martin Smith

1
@Stackoverflowuser, das obige Beispiel funktioniert, wenn Server @@ Version <2012 ist. Ab 2012 können Sie im Profiler Folgendes sehen, anstatt diese Abfrage auszuführen: exec [sys] .sp_describe_first_result_set N'SET FMTONLY OFF; EXEC ('' RESTORE HEADERONLY FROM DISK = '' '' C: \ Programme \ Microsoft SQL Server \ MSSQL10.MSSQL2008 \ MSSQL \ Backup \ DB1.bak '' '' '') ', NULL, 1
September

7

Dies ist eine versionunabhängige SP, die ich geschrieben habe, um das Sicherungsdatum aus einer Datei zu erhalten.

Es wurde für SQL 2008R2, 2012 und 2014 getestet.

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
Wie pro stackoverflow.com/a/31318785/489865 und support.microsoft.com/en-us/kb/3058865 , die KeyAlgorithm / EncryptorThumbprint / EncryptorType Sie haben nur in SP1 erschien tatsächlich für "SQL Server 2014" hinzugefügt. Ich glaube, die Build-Version dafür ist 12.0.4100.1, also sollte der Code alle Felder in betrachten SERVERPROPERTY('ProductVersion'), um dies korrekt zu berücksichtigen.
JonBrave

7

Da Sie nur nach dem Zugriff auf die Daten über "Code" gefragt haben, ohne Angaben zu der Art des Codes zu machen, stelle ich hiermit die PowerShell- Lösung vor:

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

Dies ist sogar noch besser, da wir so etwas wie `ls | machen können % {$ _. fullname} | % {invoke-sqlcmd -Query "HEADERONLY FROM DISK = '$ _'"} WIEDERHERSTELLEN} | Format-Tabelle `
Luiz Felipe

6

Der altmodische Weg als Referenz:

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
Damit dies in SQL2014 funktioniert, müssen diese zusätzlichen Felder am Ende der Tabelle stehen :, Containment tinyint, KeyAlgorithm nvarchar (32), EncryptorThumbprint varbinary (20), EncryptorType nvarchar (32)
Mike

Es gibt auch diese Antwort , die varchar nicht für alles verwendet und die zusätzlichen Spalten für SQL Server 2014 enthält.
Baodad

Beachten Sie, dass diese zusätzlichen Spalten tatsächlich in SQL 2014 SP1 hinzugefügt wurden . Ich glaube die Build Version dafür ist 12.0.4100.1.
JonBrave
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.