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

16

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. 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.) per Skript ausgeben und dann die Indexerstellungsteile des Skripts auf dem Ziel ausführen. Bei so vielen Tabellen scheint dies jedoch unpraktisch.

Wenn nicht so viele Daten vorhanden wären, könnte ich den Assistenten "Skripte erstellen ..." verwenden, um die Quelle einschließlich der Daten zu skripten. Ein Skript mit 72 m Zeilen scheint jedoch keine gute Idee zu sein!

BradC
quelle
Und es sind nicht alle Tabellen in der Datenbank?
Donnerstag,
@ thursdaysgeek: Es sind fast alle Tabellen, aber die Zieldatenbank enthält bereits über 100 Tabellen. Nur eine Wiederherstellung von einem Backup mit einem anderen Namen ist daher keine Option. Stellen Sie sich dies als "Zusammenführen dieser beiden großen Datenbanken" vor.
BradC

Antworten:

14

Das Skripten der Tabellen und die anschließende Verwendung von SSIS zum Übertragen der Daten wäre die zuverlässigste und effektivste Methode, um die Daten in die neue Datenbank zu verschieben.

mrdenny
quelle
9

Wir haben es tatsächlich mit viel manueller Skripterstellung in Verbindung mit dem Import-Assistenten gemacht, aber heute Morgen habe ich dank Tibor Karaszis Blog-Artikel eine bessere Antwort gefunden .

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

DTS-Import-Assistent

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

Erweiterte Optionen

Diese Option wurde vom SQL 2005/ 2008- Importassistenten ENTFERNT . Warum? Keine Ahnung:

2008 Import-Assistent

In 2005/2008 müssen Sie anscheinend ein SSIS-Paket in BIDS manuell erstellen und die Task "SQL Server-Objekte übertragen" verwenden , die dieselben Optionen enthält, die im 2000-Assistenten enthalten waren:

Task zum Übertragen von SQL Server-Objekten mit SSIS

BradC
quelle
Ich wollte nur posten, dass ich diese SSIS-Methode für eine andere ähnliche Aufgabe verwendet habe, und sie hat großartig funktioniert!
BradC
8

Ich würde in Betracht ziehen, die Tabelle als Skript zu erstellen oder Vergleichstools (z. B. Red Gate) zu verwenden, um die Tabellen in der Zieldatenbank zu generieren. Noch ohne Indexe oder Einschränkungen.

Dann würde ich erwägen, die Datenbank mit einem anderen Namen auf dem gleichen Server wiederherzustellen und zu tun

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

.. für jede Tabelle, bei Bedarf mit SET IDENTITY INSERT ON

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

Es hängt von Ihrem Komfortniveau mit SSIS (die Antwort von mrdenny) ab, oder ob Sie rohes SQL bevorzugen.

gbn
quelle
6

Ich würde Herrn Dennys Antwort hinzufügen: Schreiben Sie das Tabellenschema aus und verwenden Sie dann BCP, um die Daten zu verschieben. Wenn Sie nicht mit SSIS vertraut sind, sollten die Verwendung von BCP und Batches einfach sein. Für Millionen von Zeilen ist nichts besser als BCP (Bulk Insert) :).

Marian
quelle
4

Ich bin derjenige, der mit SSIS völlig unwohl ist.

Wenn die Quelltabellen keine Identitätsspalten haben

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

Nun die T-SQL, um die Select * into ... -Anweisungen zu generieren

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 kopiert werden soll

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

Für den Fall, dass die Tabellen Identitätsspalten enthalten, schreibe ich die Tabellen mit Identitätseigenschaft und Primärschlüsseln.

In diesem Fall verwende ich Einfügen in ... Auswählen ... nicht über einen Verbindungsserver, da dies keine Massentechnik ist. Ich arbeite an einigen PowerShell-Skripten, die [dieser SO-Frage 1] ähneln , aber ich arbeite immer noch an der Fehlerbehandlung. Wirklich große Tabellen können Speicherfehler verursachen, 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.

bernd_k
quelle
Falls die Tabellen Identitätsspalten enthalten, können Sie dies wie in dieser Frage tun . Das erspart Ihnen manuelle Arbeit. Ich bevorzuge weiterhin Bulk-Insert-Batches / SSIS. In einem breiten Netzwerk ist ein Verbindungsserver möglicherweise keine gute Lösung.
Marian
1
@Marian Schauen Sie unter dba.stackexchange.com/questions/297/… nach, wenn Sie für SSIS werben möchten. Ich habe SSIS nicht ausprobiert, aber der Import-Export-Assistent ist ebenfalls fehlgeschlagen (neben dem Verbindungsserver).
bernd_k
Ich hätte gerne geholfen, aber ich habe keine Oracle-Box zur Verfügung. Sowieso, nach dem, was ich gelesen habe, gibt es keine Anbieter, die Oracle CLOB unterstützen.
Marian
Ich bin dabei - ich migriere manchmal Daten, verwende jedoch niemals SSIS.
AK
2

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 Datenbank (alle Tabellen sind vorhanden, aber alle leer), um die Datensätze in die Tabellen einzufügen

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

Das Gute an diesem Vorgang 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 mehrere Gigs sind) 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

Carol Baker West
quelle
1

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 zum Einfügen von Daten anstelle von SSIS BCP

  1. bcp die Daten mit dem folgenden Skript aus. Setzen Sie SSMS in den Textmodus und kopieren Sie die vom unten stehenden Skript erzeugte 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 einheitlichen Modus verwendet.

Kin Shah
quelle