Extrayendo un campo de RESTORE HEADERONLY


12

Estoy tratando de usar ' RESTORE HEADERONLY ' para obtener la fecha en que se realizó la copia de seguridad que estoy a punto de restaurar.

El comando:

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

funciona bien en el Analizador de consultas y proporciona un conjunto de resultados con algo así como 50 columnas.

El problema es realmente acceder a esto desde el código.

Puedo obtener esto en una tabla temporal declarando cada una de las 50 columnas: ish, insertando execy obteniendo el valor que deseo a partir de ahí.

El problema es que realmente quiero evitar tener que declarar todo el conjunto de resultados como una tabla temporal, ya que parece una solución muy frágil si alguna vez le agregan columnas en versiones futuras.

¿Hay alguna forma de obtener una sola columna de este conjunto de resultados sin declarar todas las columnas?

Respuestas:


12

Esto funciona para mi.

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

La opción de consultas distribuidas ad hoc debe estar habilitada. O si no desea hacerlo, puede configurar un servidor vinculado de bucle invertido y usarlo en su lugar.

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

Inteligente, y gracias por compartir, pero solo para el registro, creo que esto es tan frágil / complejo como la gran lista de columnas al final. Es una pena que no haya una solución elegante.
Tim Abell

@TimAbell: Sí, no creo que realmente use esto en la práctica, excepto tal vez para obtener la definición de la tabla en primer lugar.
Martin Smith

1
No pude hacer que ninguna de las consultas funcionara. ¿Alguien más recibe el mensaje de error "No se pudieron determinar los metadatos porque la instrucción RESTORE HEADERONLY ... no admite el descubrimiento de metadatos"? Creo que el sp_describe_first_result_setsistema sp es el culpable. También planteé esta pregunta como un boleto separado aquí
Stackoverflowuser

@Stackoverflowuser: parece que originalmente probé esto en una instancia de 2008 (de MARTINPC\MSSQL2008), por lo que tal vez algo ha cambiado en versiones posteriores, lo que significa que esto ya no funciona.
Martin Smith

1
@Stackoverflowuser, el ejemplo anterior funciona cuando el servidor @@ versión <2012. A partir de 2012, en lugar de ejecutar esta consulta, puede ver en Profiler este: exec [sys] .sp_describe_first_result_set N'SET FMTONLY OFF; EXEC ('' RESTORE HEADERONLY FROM DISK = '' '' C: \ Archivos de programa \ Microsoft SQL Server \ MSSQL10.MSSQL2008 \ MSSQL \ Backup \ DB1.bak '' '' '') ', NULL, 1
sepupic

7

Esta es una versión independiente que escribí para obtener la fecha de respaldo de un archivo.

Se probó para SQL 2008R2, 2012 y 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
Según stackoverflow.com/a/31318785/489865 y support.microsoft.com/en-us/kb/3058865 , el KeyAlgorithm / EncryptorThumbprint / EncryptorType que agregó para "SQL SERVER 2014" en realidad solo apareció en SP1. Creo que la versión de compilación para eso es 12.0.4100.1, por lo que el código debe mirar todos los campos SERVERPROPERTY('ProductVersion')para atenderlo correctamente.
JonBrave

7

Dado que solo solicitó acceso a los datos desde 'código' sin especificar ningún tipo de código, por la presente presento la solución PowerShell :

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

1
Esto es aún mejor, ya que podemos hacer algo como `ls | % {$ _. nombre completo} | % {invoke-sqlcmd -Query "RESTORE HEADERONLY FROM DISK = '$ _'"} | format-table `
Luiz Felipe

6

La forma antigua, como referencia:

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
Para que esto funcione en SQL2014, necesitará tener estos campos adicionales al final de la tabla:, Containment tinyint, KeyAlgorithm nvarchar (32), EncryptorThumbprint varbinary (20), EncryptorType nvarchar (32)
Mike

También existe esta respuesta , que no usa varchar para todo, e incluye las columnas adicionales para SQL Server 2014.
Baodad

Tenga en cuenta que estas columnas adicionales se agregaron en realidad en SQL 2014 SP1 . Creo que la versión de compilación para eso es 12.0.4100.1.
JonBrave
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.