Jak w kopii kalejdoskopie odtworzyć wskazaną kopię
Dzisiaj przykład skryptu SQL, który pozwala na serwerze MSSQL 2008r2 odtworzyć kopię dowolnej bazy danych, umieszczoną w dowolnej, dostępnej dla serwera SQL lokalizacji, na dowolną bazę danych serwera. Skrypt wymaga podania dwóch parametrów (które należy wprowadzić do dwóch, zadeklarowanych jako pierwsze, zmiennych) tj. ścieżki do kopii bezpieczeństwa oraz nazwy bazy danych. Wszystkie pozostałe informacje skrypt pobiera sobie automatycznie, czyli będzie w stanie rozpoznać gdzie mają zostać umieszczone pliki bazy (w domyślnej lokalizacji czy może jest jakaś dedykowana), zmienić ich nazwę.
Osobiście najczęściej używam tego skryptu do odtwarzania baz, które trafiają do mnie do analizy.
Małe wyjaśnienie. Poniżej w jednej z linii użyłem kilkakrotnie Char(92) jedynie dlatego, aby obejść problem prezentacji kodu. Interpreter w przypadku napotkania znaku \ i apostrofu traktował je jak apostrof (choć wyświetlał prawidłowo), przez co reszta kodu wyglądała jak łańcuch tekstu. Docelowo można po prostu zastąpić wywołania poprzez \.
-- skrypt odtwarzający dowolną kopię bezpieczeństwa na serwerze 2008r2 declare @Backup nvarchar(255) = '', -- tutaj wprowadzić pełną ścieżkę do kopii bezpieczeństwa (serwer SQL musi mieć do nie prawa do odczytu) @DB nvarchar(255) = '', -- tutaj wprowadzić nazwę bazy danych do której ma być odtworzona kopia bezpieczeństwa @RootKeyName varchar(100) = 'HKEY_LOCAL_MACHINE', @OutputMode varchar(100) = 'no_output', @MainReg varchar(100) = 'SOFTWARE\Microsoft\Microsoft SQL Server' + Char(92), @Instance varchar(100), @InstanceKey varchar(100), @Txt nvarchar(255), @SQL nvarchar(255), @MainFolder nvarchar(255), @Folder nvarchar(255), @DataFile nvarchar(255), @LogFile nvarchar(255), @Data nvarchar(255), @Log nvarchar(255); if (@Backup = '') or (@DB = '') begin raiserror('Nie sprecyzowano folderu zawierającego kopię bezpieczeństwa lub nie określono nazwy odtwarzanej bazy danych', 16, 1); return; end; select @Instance = Convert(varchar(100), SERVERPROPERTY('instancename')), -- pobranie nazwy instancji, w ramach której funkcjonuje obecny kod @Txt = @MainReg + 'Instance Names\SQL'; -- gałąź zawierająca nazwy instancji exec master.dbo.xp_regread @rootkey = @RootKeyName, @key = @Txt, @value_name = @Instance, @value = @InstanceKey output, @output = @OutputMode; -- ustalenie folderu danych set @Txt = @MainReg + @InstanceKey + '\Setup'; -- gałąź zawierająca nazwy folderów exec master.dbo.xp_regread @rootkey = @RootKeyName, @key = @Txt, @value_name = 'SQLDataRoot', @value = @MainFolder output, @output = @OutputMode; -- ustalenie folderu z danymi dla użytkownika set @Txt = @MainReg + @InstanceKey + '\MSSQLServer'; -- gałąź zawierająca nazwy folderów exec master.dbo.xp_regread @rootkey = @RootKeyName, @key = @Txt, @value_name = 'DefaultData', @value = @Folder output, @output = @OutputMode; set @Folder = IsNull(@Folder, @MainFolder + '\Data'); -- przygotowanie polecenia określającego nazwy logiczne plików bazy oraz ustalenie nazw folderów select @SQL = 'restore filelistonly from disk = N''' + @Backup + '''', @DataFile = @Folder + Char(92) + @DB + '.MDF', @LogFile = @Folder + Char(92) + @DB + '.LDF'; -- tabela na wynik restore filelistonly if object_id('tempdb..#Result') is not null drop table #Result; create table #Result ( LogicalName nvarchar(128), PhysicalName nvarchar(260), Kind char(1), FileGroupName nvarchar(128), Size numeric(20, 0), MaxSize numeric(20, 0), FileID bigint, CreateLSN numeric(25, 0), DropLSN numeric(25, 0) NULL, UniqueID uniqueidentifier, ReadOnlyLSN numeric(25, 0) NULL, ReadWriteLSN numeric(25, 0) NULL, BackupSizeInBytes bigint, SourceBlockSize int, FileGroupID int, LogGroupGUID uniqueidentifier NULL, DifferentialBaseLSN numeric(25, 0) NULL, DifferentialBaseGUID uniqueidentifier, IsReadOnly bit, IsPresent bit, TDEThumbprint varbinary(32) ); -- ustalenie logicznych nazw plików bazy insert into #Result exec (@SQL); select @Data = max(case Kind when 'D' then LogicalName else '' end), @Log = max(case Kind when 'L' then LogicalName else '' end) from #Result; -- odtworzenie bazy z kopii bezpieczeństwa restore database @DB from disk = @Backup with file = 1, move @Data TO @DataFile, move @Log TO @LogFile, nounload, stats = 10;