Estrazione di un campo da RESTORE HEADERONLY


12

Sto cercando di utilizzare ' RESTORE HEADERONLY ' per ottenere la data in cui è stato eseguito il backup che sto per ripristinare.

Il comando:

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

funziona bene in Query Analyzer e fornisce un gruppo di risultati con qualcosa come 50 colonne.

Il problema sta effettivamente accedendo a questo dal codice.

Posso ottenere questo in una tabella temporanea dichiarando ogni singola delle colonne 50: ish, inserendola exece ottenendo il valore che desidero da lì.

Il problema è che voglio davvero evitare di dover dichiarare l'intero gruppo di risultati come tabella temporanea in quanto sembra una soluzione molto fragile se mai aggiungessero colonne ad esso nelle versioni future.

C'è un modo per ottenere una sola colonna da questo gruppo di risultati senza dichiarare tutte le colonne?

Risposte:


12

Questo funziona per me.

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

L' opzione Query distribuita ad hoc deve essere abilitata. Oppure, se non vuoi farlo, puoi configurare un server collegato in loopback e usarlo invece.

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

Intelligente e grazie per la condivisione, ma solo per la cronaca, penso che questo sia fragile / complesso come la grande lista di colonne alla fine. Peccato che non ci sia una soluzione elegante.
Tim Abell,

@TimAbell - Sì, non penso che lo userei in pratica, tranne forse per ottenere la definizione della tabella in primo luogo.
Martin Smith,

1
Non sono riuscito a far funzionare entrambe le query. Qualcun altro riceve il messaggio di errore "Impossibile determinare i metadati perché l'istruzione RESTORE HEADERONLY ... non supporta il rilevamento dei metadati"? Credo che sp_describe_first_result_setsystem sp sia il colpevole dietro. Ho anche sollevato questa domanda come biglietto separato qui
Stackoverflowuser,

@Stackoverflowuser: sembra che inizialmente lo abbia provato su un'istanza del 2008 (da MARTINPC\MSSQL2008), quindi forse qualcosa è cambiato nelle versioni successive, il che significa che non funziona più.
Martin Smith,

1
@Stackoverflowuser, l'esempio sopra funziona quando server @@ versione <2012. A partire dal 2012, invece di eseguire questa query, puoi vedere in Profiler questo: exec [sys] .sp_describe_first_result_set N'SET FMTONLY OFF; EXEC ('' RESTORE HEADERONLY FROM DISK = '' '' C: \ Programmi \ Microsoft SQL Server \ MSSQL10.MSSQL2008 \ MSSQL \ Backup \ DB1.bak '' '' '') ', NULL, 1
sepupic

7

Questa è una versione indipendente sp che ho scritto per ottenere la data di backup da un file.

È testato per SQL 2008R2, 2012 e 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
Come per stackoverflow.com/a/31318785/489865 e support.microsoft.com/en-us/kb/3058865 , il KeyAlgorithm / EncryptorThumbprint / EncryptorType aver aggiunto per "SQL Server 2014" in realtà è apparso solo in SP1. Credo che la versione build sia quella 12.0.4100.1, quindi il codice dovrebbe esaminare tutti i campi SERVERPROPERTY('ProductVersion')per soddisfare correttamente.
JonBrave,

7

Dato che hai chiesto di accedere ai dati solo da 'code' senza specificare alcun tipo di codice, ti presento la soluzione PowerShell :

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

1
Questo è ancora meglio, dato che possiamo fare qualcosa come `ls | % {$ _. fullname} | % {invoke-sqlcmd -Query "RIPRISTINA INIZIALE DAL DISCO = '$ _'"} | format-table `
Luiz Felipe,

6

Alla vecchia maniera, per riferimento:

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
Per farlo funzionare in SQL2014, è necessario disporre di questi campi aggiuntivi alla fine della tabella:, Contenimento tinyint, KeyAlgorithm nvarchar (32), EncryptorThumbprint varbinary (20), EncryptorType nvarchar (32)
Mike

C'è anche questa risposta , che non usa varchar per tutto e include le colonne extra per SQL Server 2014.
Baodad

Si noti che queste colonne aggiuntive sono state effettivamente aggiunte in SQL 2014 SP1 . Credo che la versione build sia quella 12.0.4100.1.
JonBrave,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.