# ========================= # Konfiguration # ========================= $Server = ".\KEYVI" $Mode = "Test" # "Test" oder "Production" $BackupFile = "D:\SQLBackup\DB_Keyvi\2026\07\DB_Keyvi_20260729_205555.bak" $ProdDb = "DB_Keyvi" $TestDb = "DB_Keyvi_RestoreTest" # ========================= $ErrorActionPreference = "Stop" if ($Mode -notin @("Test","Production")) { throw "Ungültiger Mode '$Mode'. Erlaubt: Test oder Production." } if (-not (Test-Path $BackupFile)) { throw "Backup-Datei nicht gefunden: $BackupFile" } $TargetDb = if ($Mode -eq "Production") { $ProdDb } else { $TestDb } Write-Host "Modus: $Mode" Write-Host "Server: $Server" Write-Host "Ziel-Datenbank: $TargetDb" Write-Host "Backup-Datei: $BackupFile" if ($Mode -eq "Production") { Write-Warning "PRODUCTION-MODUS: Datenbank [$ProdDb] wird überschrieben!" $confirm = Read-Host "Tippe genau 'JA' zum Fortfahren" if ($confirm -ne "JA") { throw "Abgebrochen durch Benutzer." } } # Alles in SQL erledigen (robust, kein Text-Parsing nötig) $sql = @" USE [master]; DECLARE @BackupFile nvarchar(4000) = N'$BackupFile'; DECLARE @TargetDb sysname = N'$TargetDb'; DECLARE @DataPath nvarchar(4000) = CAST(SERVERPROPERTY('InstanceDefaultDataPath') AS nvarchar(4000)); DECLARE @LogPath nvarchar(4000) = CAST(SERVERPROPERTY('InstanceDefaultLogPath') AS nvarchar(4000)); IF @DataPath IS NULL OR @LogPath IS NULL BEGIN RAISERROR(N'InstanceDefaultDataPath/LogPath konnte nicht ermittelt werden.',16,1); RETURN; END DECLARE @filelist TABLE ( LogicalName nvarchar(128), PhysicalName nvarchar(260), [Type] char(1), FileGroupName nvarchar(128), [Size] numeric(20,0), MaxSize numeric(20,0), FileID bigint, CreateLSN numeric(25,0), DropLSN numeric(25,0), UniqueID uniqueidentifier, ReadOnlyLSN numeric(25,0), ReadWriteLSN numeric(25,0), BackupSizeInBytes bigint, SourceBlockSize int, FileGroupID int, LogGroupGUID uniqueidentifier, DifferentialBaseLSN numeric(25,0), DifferentialBaseGUID uniqueidentifier, IsReadOnly bit, IsPresent bit, TDEThumbprint varbinary(32), SnapshotURL nvarchar(360) ); DECLARE @sqlFileList nvarchar(max) = N'RESTORE FILELISTONLY FROM DISK = N''' + REPLACE(@BackupFile,'''','''''') + N''';'; INSERT INTO @filelist EXEC(@sqlFileList); DECLARE @DataLogical sysname = (SELECT TOP(1) LogicalName FROM @filelist WHERE [Type]='D' ORDER BY FileID); DECLARE @LogLogical sysname = (SELECT TOP(1) LogicalName FROM @filelist WHERE [Type]='L' ORDER BY FileID); IF @DataLogical IS NULL OR @LogLogical IS NULL BEGIN RAISERROR(N'Konnte logische Daten-/Log-Datei im Backup nicht finden.',16,1); RETURN; END DECLARE @MdfTarget nvarchar(4000) = @DataPath + @TargetDb + N'.mdf'; DECLARE @LdfTarget nvarchar(4000) = @LogPath + @TargetDb + N'_log.ldf'; IF DB_ID(@TargetDb) IS NOT NULL BEGIN DECLARE @sqlSingle nvarchar(max) = N'ALTER DATABASE [' + @TargetDb + N'] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;'; EXEC(@sqlSingle); END DECLARE @sqlRestore nvarchar(max) = N' RESTORE DATABASE [' + @TargetDb + N'] FROM DISK = N''' + REPLACE(@BackupFile,'''','''''') + N''' WITH MOVE N''' + REPLACE(@DataLogical,'''','''''') + N''' TO N''' + REPLACE(@MdfTarget,'''','''''') + N''', MOVE N''' + REPLACE(@LogLogical, '''','''''') + N''' TO N''' + REPLACE(@LdfTarget, '''','''''') + N''', REPLACE, RECOVERY, STATS = 10;'; EXEC(@sqlRestore); DECLARE @sqlMulti nvarchar(max) = N'ALTER DATABASE [' + @TargetDb + N'] SET MULTI_USER;'; EXEC(@sqlMulti); PRINT N'Restore erfolgreich: ' + @TargetDb; PRINT N'MDF: ' + @MdfTarget; PRINT N'LDF: ' + @LdfTarget; "@ sqlcmd -S $Server -E -C -b -Q $sql if ($LASTEXITCODE -ne 0) { throw "Restore fehlgeschlagen (ExitCode $LASTEXITCODE)." } Write-Host "Fertig." -ForegroundColor Green