Mengekstrak bidang dari RESTORE HEADERONLY

12

Saya mencoba menggunakan ' KEMBALIKAN HEADERONLY ' untuk mendapatkan tanggal ketika cadangan yang akan saya pulihkan telah dibuat.

Perintah:

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

berfungsi dengan baik di Query Analyzer dan memberikan hasil dengan sekitar 50 kolom.

Masalahnya sebenarnya mengakses ini dari kode.

Saya bisa mendapatkan ini ke tabel temp dengan mendeklarasikan setiap satu dari 50: kolom ish, memasukkan ke dalamnya dengan execdan mendapatkan nilai yang saya inginkan dari sana.

Masalahnya adalah bahwa saya benar-benar ingin menghindari keharusan mendeklarasikan seluruh resultset sebagai tabel temp karena sepertinya solusi yang sangat rapuh jika mereka pernah menambahkan kolom ke dalam versi masa depan.

Apakah ada cara untuk mendapatkan satu kolom saja dari resultset ini tanpa mendeklarasikan semua kolom?

alun
sumber

Jawaban:

12

Ini bekerja untuk saya.

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

The ad hoc query didistribusikan Option harus diaktifkan. Atau jika Anda tidak ingin melakukannya, Anda dapat mengatur server yang ditautkan loopback dan menggunakannya.

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''''
'')')
Martin Smith
sumber
Pintar, dan terima kasih untuk berbagi, tetapi hanya untuk catatan saya pikir ini sama rapuh / kompleksnya dengan daftar besar kolom pada akhirnya. Malu tidak ada solusi yang elegan.
Tim Abell
@ Timimbell - Ya saya tidak berpikir saya akan benar-benar menggunakan ini dalam praktek kecuali mungkin untuk mendapatkan definisi tabel di tempat pertama.
Martin Smith
1
Saya tidak dapat membuat kueri berfungsi. Apakah ada orang lain yang mendapatkan pesan kesalahan "Metadata tidak dapat ditentukan karena pernyataan RESTORE HEADERONLY ... tidak mendukung penemuan metadata"? Saya percaya sp_describe_first_result_setsistem sp adalah biang keladinya. Saya juga mengajukan pertanyaan ini sebagai tiket terpisah di sini
Stackoverflowuser
@Stackoverflowuser - sepertinya saya awalnya menguji ini terhadap contoh 2008 (dari MARTINPC\MSSQL2008) jadi mungkin ada sesuatu yang berubah di versi yang lebih baru yang berarti ini tidak lagi berfungsi.
Martin Smith
1
@Stackoverflowuser, contoh di atas berfungsi ketika server @@ versi <2012. Dimulai dengan 2012, alih-alih mengeksekusi kueri ini, Anda dapat melihat di Profiler yang ini: exec [sys] .sp_describe_first_result_set N'SET FMTONLY OFF; EXEC ('' KEMBALIKAN HEADERONLY DARI DISK = '' 'C: \ Program Files \ Microsoft SQL Server \ MSSQL10.MSSQL2008 \ MSSQL \ Backup \ DB1.bak' '' '' ')', NULL, 1
sepupic
7

Ini adalah versi independen sp yang saya tulis untuk mendapatkan tanggal cadangan dari sebuah file.

Ini diuji untuk SQL 2008R2, 2012 dan 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
pengguna3742089
sumber
1
Per stackoverflow.com/a/31318785/489865 dan support.microsoft.com/en-us/kb/3058865 , KeyAlgorithm / EncryptorThumbprint / EncryptorType yang telah Anda tambahkan untuk "SQL SERVER 2014" sebenarnya hanya muncul di SP1. Saya percaya Versi Build untuk itu 12.0.4100.1, jadi kode harus melihat semua bidang SERVERPROPERTY('ProductVersion')untuk memenuhi dengan benar untuk itu.
JonBrave
7

Karena Anda hanya bertanya tentang mengakses data dari 'kode' tanpa menentukan rincian kode apa, saya dengan ini menyajikan solusi PowerShell :

Invoke-SQLcmd -Query "RESTORE HEADERONLY FROM DISK = 'R:\SQLFiles\MSSQL.MSSQLSERVER.Backup\Backup.bak'" | Select-Object MachineName,DatabaseName,HasBackupChecksums,BackupStartDate,BackupFinishDate
Christoph Wegener
sumber
1
Ini bahkan lebih baik, karena kita dapat melakukan sesuatu seperti `ls | % {$ _. nama lengkap} | % {invoke-sqlcmd -Query "KEMBALIKAN HEADERONLY DARI DISK = '$ _'"} | format-table `
Luiz Felipe
6

Cara kuno, untuk referensi:

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;
ryscl
sumber
1
Agar ini berfungsi di SQL2014, Anda harus memiliki bidang tambahan ini di akhir tabel:, Containment tinyint, KeyAlgorithm nvarchar (32), EncryptorThumbprint varbinary (20), EncryptorType nvarchar (32)
Mike
Ada juga jawaban ini , yang tidak menggunakan varchar untuk semuanya, dan termasuk kolom tambahan untuk SQL Server 2014.
Baodad
Perhatikan bahwa kolom tambahan ini sebenarnya ditambahkan dalam SQL 2014 SP1 . Saya percaya Versi Build untuk itu 12.0.4100.1.
JonBrave