Mijn collega Sjakkie mocht voor een klant een server migratie uitvoeren van een oude SBS omgeving naar Server 2019. Hij liep daarbij tegen het probleem aan dat je een grote hoeveelheid SQL Databases op een SQL Express instance niet via de SQL Management Studio kon migreren. Hij heeft daarom een export gerealiseerd dat alle databases backupt en een import script dat de bak files inleest en in een wenste data map neerzet.
Hieronder vind je de scripts die Rooie Dokus daarvoor gebruikte. 1 script om van alle databases (exclusief systeemdatabases) een .bak te creëren en 1 script om al deze .bak bestanden te restoren.
Hieronder de SQL export query:
DECLARE @name VARCHAR(50) -- database name DECLARE @path VARCHAR(256) -- path for backup files DECLARE @fileName VARCHAR(256) -- filename for backup DECLARE @fileDate VARCHAR(20) -- used for file name -- specify database backup directory SET @path = 'D:\SQLBACKUPS\' -- specify filename format SELECT @fileDate = CONVERT(VARCHAR(20),GETDATE(),112) DECLARE db_cursor CURSOR READ_ONLY FOR SELECT name FROM master.dbo.sysdatabases WHERE name NOT IN ('master','model','msdb','tempdb') -- exclude these databases OPEN db_cursor FETCH NEXT FROM db_cursor INTO @name WHILE @@FETCH_STATUS = 0 BEGIN SET @fileName = @path + @name + '_' + @fileDate + '.BAK' BACKUP DATABASE @name TO DISK = @fileName FETCH NEXT FROM db_cursor INTO @name END CLOSE db_cursor DEALLOCATE db_cursor
Vervolgens kopieer je de database backups naar de nieuwe server. Met het volgende Powershell script voer je de restore uit.
$backupRoot = Get-ChildItem -Path "D:\SQLBACKUPS" $datafilesDest = "D:\DATA_FILE_FOLDER" $logfilesDest = "D:\LOG_FILE_FOLDER" $server = "server\inst" ## For each folder in the backup root directory... # foreach($folder in $backupRoot) { # Get the most recent .bak files for all databases... $backupFiles = Get-ChildItem -Path $folder.FullName -Filter "*.bak" -Recurse | Sort-Object -Property CreationTime -Descending | Select-Object -First 1 # For each .bak file... foreach ($backupFile in $backupFiles) { # Restore the header to get the database name... $query = "RESTORE HEADERONLY FROM DISK = N'"+$backupFile.FullName+"'" $headerInfo = Invoke-Sqlcmd -ServerInstance $server -Query $query $databaseName = $headerInfo.DatabaseName # Restore the file list to get the logical filenames of the database files... $query = "RESTORE FILELISTONLY FROM DISK = N'"+$backupFile.FullName+"'" $files = Invoke-Sqlcmd -ServerInstance $server -Query $query # Differentiate data files from log files... $dataFile = $files | Where-Object -Property Type -EQ "D" $logFile = $files | Where-Object -Property Type -EQ "L" # Set some variables... $dataFileName = $dataFile.LogicalName $logFileName = $logFile.LogicalName # Set the destination of the restored files... $dataFileFullPath = $datafilesDest+"\"+$dataFileName+".mdf" $logFileFullPath = $logfilesDest+"\"+$logFileName+".ldf" # Create some "Relocate" file objects to pass to the Restore-SqlDatabase cmdlet... $RelocateData = New-Object 'Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=12.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' -ArgumentList $dataFileName, $dataFileFullPath $RelocateLog = New-Object 'Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=12.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' -ArgumentList $logFileName, $logFileFullPath # Perform the database restore... and then go around the loop. Restore-SqlDatabase -ServerInstance $server -Database $databaseName -BackupFile $backupFile.FullName -RelocateFile @($RelocateData,$RelocateLog) -ReplaceDatabase } }
Denk aan de users die binnen de SQL instance kunnen bestaan. Deze kun je via het script op de volgende pagina overzetten.