it-swarm-eu.dev

Verschieben von Tabellen in eine andere SQL2008-Datenbank (einschließlich Indizes, Trigger usw.)

Ich muss eine ganze Reihe (100+) großer (Millionen von Zeilen) Tabellen von einer SQL2008-Datenbank in eine andere verschieben.

Ich habe ursprünglich nur den Import/Export-Assistenten verwendet, aber in allen Zieltabellen fehlten Primär- und Fremdschlüssel, Indizes, Einschränkungen, Trigger usw. (Identitätsspalten wurden ebenfalls in einfache INTs konvertiert, aber ich glaube, ich habe gerade ein Kontrollkästchen im Feld verpasst Magier.)

Was ist der richtige Weg, um dies zu tun?

Wenn dies nur ein paar Tabellen wären, würde ich zur Quelle zurückkehren, die Tabellendefinition (mit allen Indizes usw.) skripten und dann die Indexerstellungsteile des Skripts auf dem Ziel ausführen. Bei so vielen Tabellen scheint dies jedoch unpraktisch.

Wenn es nicht so viele Daten gäbe, könnte ich den Assistenten "Skripte erstellen ..." verwenden, um die Quelle einschließlich der Daten zu skripten, aber ein Skript mit 72 m Zeilen scheint einfach keine gute Idee zu sein!

16
BradC

Wir haben es tatsächlich mit vielen manuellen Skripten in Verbindung mit dem Import-Assistenten gemacht, aber heute Morgen habe ich eine bessere Antwort gefunden, mit freundlicher Genehmigung von Tibor Karaszis Blog-Artikel .

Ein Teil unserer Frustration war, dass der SQL 2000 "DTS-Import/Export-Assistent" dies durch Auswahl von "Objekte und Daten kopieren" fast trivial einfach macht:

DTS Import Wizard

Diese dritte Option enthält die Möglichkeit, Indizes/Trigger usw. einzuschließen:

Advanced Options

Diese Option wurde [~ # ~] aus dem Importassistenten SQL 2005/2008 [[# # ~] entfernt. Warum? Keine Ahnung:

2008 Import Wizard

In 2005/2008 müssen Sie anscheinend manuell ein SSIS-Paket in BIDS erstellen und SQL Server Objects Task übertragen verwenden, das dieselben Optionen enthält, die sich in befanden der 2000-Assistent:

SSIS Transfer SQL Server Objects Task

9
BradC

Das Ausschreiben der Tabellen und das anschließende Übertragen der Daten mit SSIS ist die zuverlässigste und effektivste Methode, um die Daten in die neue Datenbank zu verschieben.

14
mrdenny

Ich würde in Betracht ziehen, die Tabelle zu skripten oder ein Vergleichstool (z. B. Red Gate) zu verwenden, um die Tabellen in der Zieldatenbank zu generieren. Noch ohne Indizes oder Einschränkungen.

Dann würde ich in Betracht ziehen, die Datenbank mit einem anderen Namen auf demselben Server wiederherzustellen und dies zu tun

 INSERT newdb.dbo.newtable SELECT * FROM olddb.dbo.oldtable

.. für jede Tabelle mit SET IDENTITY INSERT ON, falls erforderlich

Dann würde ich nach dem Laden der Daten Indizes und Einschränkungen hinzufügen.

Dies hängt von Ihrem Komfortniveau mit SSIS (Antwort von mrdenny) ab oder davon, ob Sie Raw SQL bevorzugen.

8
gbn

Ich würde die Antwort von Herrn Denny ergänzen: Schreiben Sie das Tabellenschema aus und verschieben Sie die Daten mit BCP. Wenn Sie mit SSIS nicht vertraut sind, sollte die Verwendung von BCP und Batches einfach sein. Für Millionen von Zeilen geht nichts über BCP (Bulk Insert) :).

6
Marian

Ich bin derjenige, der sich mit SSIS völlig unwohl fühlt.

Wenn die Quelltabellen keine Identitätsspalten haben

  1. erstellen Sie eine leere Datenbank auf dem Zielserver
  2. erstellen Sie einen Verbindungsserver zum Quellserver auf dem Zielserver
  3. führen Sie das folgende Skript in der Quellendatenbank aus, um select * in ... -Anweisungen zu generieren
  4. führen Sie das generierte Skript aus der Zieldatenbank aus
  5. skriptprimärschlüssel, Indizes, Trigger, Funktionen und Prozeduren aus der Quellendatenbank
  6. erstellen Sie diese Objekte mit dem generierten Skript

Nun generiert das T-SQL die Select * in ... -Anweisungen

SET NOCOUNT ON

declare @name sysname
declare @sql varchar(255)

declare db_cursor cursor for
select name from sys.tables order by 1
open db_cursor

fetch next from db_cursor into @name
while @@FETCH_STATUS = 0
begin
    Set @sql = 'select * into [' + @name + '] from [linked_server].[source_db].[dbo].[' + @name + '];'
    print @sql

    fetch next from db_cursor into @name
end

close db_cursor
deallocate db_cursor

Dies erzeugt eine Zeile für jede Tabelle, die wie kopiert werden soll

select * into [Table1] from [linked_server].[source_db].[dbo].[Table1];

Für den Fall, dass die Tabellen Identitätsspalten enthalten, skripte ich die Tabellen einschließlich Identitätseigenschaft und Primärschlüssel.

Ich verwende in diesem Fall nicht das Einfügen in ... auswählen ... über einen Verbindungsserver, da dies keine Massentechnik ist. Ich arbeite an einigen PowerShell-Skripten ähnlich [this SO question 1 , aber ich arbeite immer noch an der Fehlerbehandlung. Wirklich große Tabellen können zu Speichermangel führen Fehler, da eine ganze Tabelle in den Speicher geladen wird, bevor sie über SQLBulkCopy an die Datenbank gesendet wird.

Die Neuerstellung von Indizes usw. ähnelt dem obigen Fall. Dieses Mal kann ich die Neuerstellung der Primärschlüssel überspringen.

4
bernd_k

Sie können Vergleichstools verwenden, die Datenbankschemata und -daten vergleichen und zuerst ein leeres Datenbankschema mit der ursprünglichen Datenbank synchronisieren, um alle Tabellen zu erstellen.

Synchronisieren Sie dann die Daten aus der ursprünglichen Datenbank mit der neuen (alle Tabellen sind vorhanden, aber alle leer), um die Datensätze in die Tabellen einzufügen

Ich benutze dafür ApexSQL Diff und ApexSQL Data Diff , aber es gibt andere ähnliche Tools.

Das Gute an diesem Prozess ist, dass Sie die Datenbanken nicht mit dem Tool synchronisieren müssen, da dies für Millionen von Zeilen sehr schmerzhaft sein kann.

Sie können einfach ein INSERT INTO SQL-Skript erstellen (wundern Sie sich nicht, wenn es sich um mehrere Gigs handelt) und es ausführen.

Da so große Skripte nicht einmal in SQL Server Management Studio geöffnet werden können, verwende ich sqlcmd oder osql

2

Wie @mrdenny erwähnt -

  1. schreiben Sie zuerst Tabellen mit allen Indizes, FKs usw. aus und erstellen Sie leere Tabellen in der Zieldatenbank.

Verwenden Sie anstelle von SSIS BCP, um Daten einzufügen

  1. bcp die Daten mit dem folgenden Skript aus. Stellen Sie SSMS in den Textmodus und kopieren Sie die vom folgenden Skript generierte Ausgabe in eine Bat-Datei.

    -- save below output in a bat file by executing below in SSMS in TEXT mode
    
    -- clean up: create a bat file with this command --> del D:\BCP\*.dat 
    
    select '"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\bcp.exe" ' /* path to BCP.exe */
        +  QUOTENAME(DB_NAME())+ '.' /* Current Database */
        +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.'            
        +  QUOTENAME(name)  
        +  ' out D:\BCP\'  /* Path where BCP out files will be stored */
        +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
        +  REPLACE(name,' ','') 
        + '.dat -T -E -SServerName\Instance -n' /* ServerName, -E will take care of Identity, -n is for Native Format */
    from sys.tables
    where is_ms_shipped = 0 and name <> 'sysdiagrams'                       /* sysdiagrams is classified my MS as UserTable and we dont want it */
    /*and schema_name(schema_id) <> 'unwantedschema'    */                             /* Optional to exclude any schema  */
    order by schema_name(schema_id)
    
  2. Führen Sie die bat-Datei aus, die die .dat-Dateien in dem von Ihnen angegebenen Ordner generiert.

  3. Führen Sie das folgende Skript auf dem aus

    --- Execute this on the destination server.database from SSMS.
    
    --- Make sure the change the @Destdbname and the bcp out path as per your environment.
    
    declare @Destdbname sysname
    set @Destdbname = 'destinationDB' /* Destination Database Name where you want to Bulk Insert in */
    select 'BULK INSERT ' 
    /*Remember Tables must be present on destination database */ 
    + QUOTENAME(@Destdbname) + '.' 
    + QUOTENAME(SCHEMA_NAME(SCHEMA_ID)) 
    + '.' + QUOTENAME(name) 
    + ' from ''D:\BCP\' /* Change here for bcp out path */ 
    + REPLACE(SCHEMA_NAME(schema_id), ' ', '') + '_' + REPLACE(name, ' ', '') 
    + '.dat'' with ( KEEPIDENTITY, DATAFILETYPE = ''native'', TABLOCK )' 
    + char(10) 
    + 'print ''Bulk insert for ' + REPLACE(SCHEMA_NAME(schema_id), ' ', '') + '_' + REPLACE(name, ' ', '') + ' is done... ''' 
    + char(10) + 'go'
       from sys.tables
       where is_ms_shipped = 0
    and name <> 'sysdiagrams' /* sysdiagrams is classified my MS as UserTable and we dont want it */
    and schema_name(schema_id) <> 'unwantedschema' /* Optional to exclude any schema */
        order by schema_name(schema_id) 
    
  4. Führen Sie die Ausgabe mit SSMS aus, um Daten wieder in die Tabellen einzufügen.

Dies ist eine sehr schnelle bcp-Methode, da sie den Native-Modus verwendet.

1
Kin Shah