Zweck

Fügt alle Datenbanken in einem Verzeichnis dem SQL Server hinzu. 
Dies wird oftmals für schnelle Server Umzüge genutzt.

Hinweise zur Verwendung

  • Ausführungsumgebung: Das Skript muss auf einem Windows-basierten SQL Server mit aktivierten xp_cmdshell-Berechtigungen (sysadmin) ausgeführt werden.

  • Test vor Produktion: Führen Sie das Skript zuerst mit einer Kopie der MDF-Dateien aus, um unerwartete Seiteneffekte zu vermeiden.

  • Transaktionslogs: Nach einem CREATE DATABASE ... FOR ATTACH wird das zugehörige Logfile (.ldf) erwartet. Wenn es fehlt, versucht SQL Server, ein neues Log zu erstellen – dies kann fehlschlagen, wenn die Datenbank nicht ordnungsgemäß heruntergefahren wurde.

  • Berechtigungen: Der SQL Server-Dienst muss Lese- und Schreibzugriff auf das Verzeichnis @AttachFromDir haben.

  • Keine Unterstützung für Dateigruppen: Das Skript ignoriert sekundäre Dateien (.ndf). Datenbanken mit mehreren Dateigruppen können nicht korrekt angehängt werden.

-- =====================================================================
-- Skript: Automatisches Anhängen von Datenbanken aus einem Verzeichnis
-- Autor:   (Ihr Name)
-- Datum:   (aktuelles Datum)
-- 
-- Zweck:
--   Durchsucht ein angegebenes Verzeichnis nach .mdf-Dateien und hängt
--   jede Datenbank an die aktuelle SQL Server-Instanz an, sofern:
--     - Die Datenbank noch nicht existiert.
--     - Die interne Datenbankversion nicht neuer ist als die des Servers.
-- 
-- Sicherheit:
--   Benötigt Mitgliedschaft in der festen Serverrolle 'sysadmin'.
--   Vorübergehende Aktivierung von xp_cmdshell wird nach der Ausführung
--   in den ursprünglichen Zustand zurückversetzt.
-- 
-- Einschränkungen:
--   - Funktioniert nur mit Datenbanken, die aus einer einzelnen .mdf-Datei
--     bestehen (keine zusätzlichen .ndf oder separate .ldf).
--   - Nur Laufwerksbuchstaben (z.B. D:\) werden unterstützt; UNC-Pfade
--     (\\server\share) nicht.
--   - Die .mdf-Dateien müssen den primären Datenbanknamen als Basis haben.
--   - Die Dateien müssen direkt im angegebenen Ordner liegen (keine Unterordner).
-- 
-- Änderungshistorie:
--   [Datum]  Initiale Version (korrigiert und erweitert)
-- =====================================================================

SET NOCOUNT ON;

DECLARE @AttachFromDir nvarchar(500) = N'F:\Daten\SQL'   -- Hier das Quellverzeichnis anpassen

-- Tabellen für Dateiliste und Prüfergebnisse
DECLARE @TabFileNames TABLE (FileName nvarchar(260));
DECLARE @TabFileAttribiute TABLE (attrName sql_variant, attrValue sql_variant);

-- Variablen für Cursor und Verarbeitung
DECLARE @readDirCmd    nvarchar(1000);
DECLARE @Aktuell       nvarchar(160);
DECLARE @dbs           nvarchar(256);
DECLARE @phys_name     nvarchar(520);
DECLARE @dbccstmt      nvarchar(1000);
DECLARE @dbsVersionAttach INT;
DECLARE @VersionServer INT;

-- =====================================================================
-- 1. Vorbereitung: xp_cmdshell-Zustand sichern
-- =====================================================================
DECLARE @cmdshell_was_activated INT;
SELECT @cmdshell_was_activated = CAST(value_in_use AS INT)
FROM sys.configurations
WHERE name = 'xp_cmdshell';

IF @cmdshell_was_activated = 0
BEGIN
    EXEC sp_configure 'show advanced options', 1;
    RECONFIGURE;
    EXEC sp_configure 'xp_cmdshell', 1;
    RECONFIGURE;
END

-- =====================================================================
-- 2. Dateiliste aus Verzeichnis holen
-- =====================================================================
SET @readDirCmd = N'dir /b "' + @AttachFromDir + N'"\*.mdf';
INSERT INTO @TabFileNames (FileName)
EXEC xp_cmdshell @readDirCmd;

-- Ungültige Einträge entfernen (NULL, "File Not Found", leere Zeilen)
DELETE FROM @TabFileNames
WHERE FileName IS NULL 
   OR FileName = 'File Not Found'
   OR LTRIM(RTRIM(FileName)) = '';

-- =====================================================================
-- 3. Bereits angehängte Datenbankdateien herausfiltern
-- =====================================================================
DELETE a
FROM @TabFileNames a
INNER JOIN sys.master_files b
    ON UPPER(@AttachFromDir + N'\' + a.FileName) = UPPER(b.physical_name);

-- Falls keine Dateien übrig sind, abbrechen
IF NOT EXISTS (SELECT 1 FROM @TabFileNames)
BEGIN
    PRINT N'Keine neuen Dateien gefunden. Prüfen Sie das Verzeichnis: ' + @AttachFromDir;
    GOTO Cleanup;
END

-- =====================================================================
-- 4. Version des Servers ermitteln
-- =====================================================================
SELECT @VersionServer = CONVERT(INT, DATABASEPROPERTYEX('master', 'version'));

-- =====================================================================
-- 5. Cursor über die verbleibenden Dateien
-- =====================================================================
DECLARE cf CURSOR LOCAL FAST_FORWARD FOR
    SELECT FileName FROM @TabFileNames ORDER BY FileName;

OPEN cf;
FETCH NEXT FROM cf INTO @Aktuell;

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        SET @phys_name = @AttachFromDir + N'\' + @Aktuell;
        SET @dbccstmt = N'DBCC CHECKPRIMARYFILE (' + QUOTENAME(@phys_name, '"') + N', 2)';

        -- Prüfinformationen aus der MDF-Datei holen
        DELETE FROM @TabFileAttribiute;   -- Vorherige Daten löschen
        INSERT INTO @TabFileAttribiute
        EXEC (@dbccstmt);

        -- Datenbanknamen extrahieren
        SELECT @dbs = CONVERT(nvarchar(256), attrValue)
        FROM @TabFileAttribiute
        WHERE attrName = 'Database name';

        -- Datenbankversion der Datei extrahieren
        SELECT @dbsVersionAttach = CONVERT(INT, attrValue)
        FROM @TabFileAttribiute
        WHERE attrName = 'Database version';

        -- Prüfen, ob Datenbank bereits existiert oder Version zu hoch ist
        IF (@dbsVersionAttach > @VersionServer)
        BEGIN
            PRINT N'[Übersprungen] ' + @dbs + N' – Datenbankversion (' + CAST(@dbsVersionAttach AS nvarchar) + 
                  N') ist neuer als Serverversion (' + CAST(@VersionServer AS nvarchar) + N').';
        END
        ELSE IF EXISTS (SELECT 1 FROM sys.databases WHERE name = @dbs)
        BEGIN
            PRINT N'[Übersprungen] ' + @dbs + N' – Datenbank ist bereits am Server vorhanden.';
        END
        ELSE
        BEGIN
            -- Attach mit CREATE DATABASE (modern, statt sp_attach_single_file_db)
            DECLARE @attachSQL nvarchar(2000);
            SET @attachSQL = N'CREATE DATABASE ' + QUOTENAME(@dbs) + 
                             N' ON (FILENAME = ' + QUOTENAME(@phys_name, '''') + N') ' +
                             N'FOR ATTACH;';
            EXEC sp_executesql @attachSQL;

            PRINT N'[Erfolg]   Datenbank "' + @dbs + N'" angehängt von Datei: ' + @Aktuell;
        END

    END TRY
    BEGIN CATCH
        PRINT N'[Fehler]   Bei Datei "' + @Aktuell + N'": ' + ERROR_MESSAGE();
    END CATCH

    -- Temporäre Tabelle für nächsten Durchlauf leeren
    DELETE FROM @TabFileAttribiute;

    FETCH NEXT FROM cf INTO @Aktuell;
END

CLOSE cf;
DEALLOCATE cf;

-- =====================================================================
-- 6. Aufräumen: xp_cmdshell auf ursprünglichen Zustand zurücksetzen
-- =====================================================================
Cleanup:
IF @cmdshell_was_activated = 0
BEGIN
    EXEC sp_configure 'xp_cmdshell', 0;
    RECONFIGURE;
    EXEC sp_configure 'show advanced options', 0;
    RECONFIGURE;
END

SET NOCOUNT OFF;

 

 

 

 

Cookies user preferences
We use cookies to ensure you to get the best experience on our website. If you decline the use of cookies, this website may not function as expected.
Accept all
Decline all
Analytics
Tools used to analyze the data to measure the effectiveness of a website and to understand how it works.
Google Analytics
Advertisement
If you accept, the ads on the page will be adapted to your preferences.
Google Ad
Save