Spostamento di tabelle in un altro database SQL2008 (inclusi indici, trigger, ecc.)


16

Devo spostare un intero gruppo (100+) di tabelle di grandi dimensioni (milioni di righe) da un database SQL2008 a un altro.

Inizialmente ho usato l'importazione / esportazione guidata, ma in tutte le tabelle di destinazione mancavano chiavi primarie ed esterne, indici, vincoli, trigger, ecc. (Anche le colonne Identity sono state convertite in semplici INT, ma penso di aver perso una casella nella procedura guidata.)

Qual è il modo giusto per farlo?

Se questo fosse solo un paio di tabelle, ritornerei alla fonte, scrivo la definizione della tabella (con tutti gli indici, ecc.), Quindi eseguo le parti di creazione dell'indice dello script sulla destinazione. Ma con così tanti tavoli, questo sembra poco pratico.

Se non ci fossero così tanti dati, potrei usare la procedura guidata "Crea script ..." per scrivere la fonte, inclusi i dati, ma uno script di 72 m di riga non sembra una buona idea!


E non sono tutte le tabelle nel database?
giovedì giovedì

@thursdaysgeek: sono quasi tutte le tabelle, ma il database di destinazione ha già più di 100 tabelle. Quindi, solo il ripristino dal backup con un nome diverso non è un'opzione. Pensa a questo essenzialmente come "unisci insieme questi due grandi database".
BradC,

Risposte:


14

Lo scripting delle tabelle, quindi l'utilizzo di SSIS per trasferire i dati sarebbe il modo più affidabile ed efficace per spostare i dati nel nuovo database.


9

In realtà l'abbiamo fatto usando molti script manuali insieme alla procedura guidata di importazione, ma questa mattina ho trovato una risposta migliore, per gentile concessione dell'articolo del blog di Tibor Karaszi .

Parte della nostra frustrazione qui è stata che la "Procedura guidata di importazione / esportazione DTS" di SQL 2000 in realtà lo rende quasi banalmente facile selezionando "Copia oggetti e dati":

Importazione guidata DTS

Questa terza opzione è quella che contiene la possibilità di includere indici / trigger, ecc:

Opzioni avanzate

Questa opzione è stata RIMOSSA dal SQL 2005/2008 importazione guidata. Perché? Nessuna idea:

Importazione guidata 2008

Nel 2005/2008, apparentemente devi creare manualmente un pacchetto SSIS in BIDS e utilizzare l'attività Trasferisci oggetti SQL Server , che contiene tutte le stesse opzioni presenti nella procedura guidata 2000:

Attività SSIS Trasferimento oggetti SQL Server


Volevo solo postare che ho usato questo metodo SSIS per un'altra attività simile, e ha funzionato benissimo!
BradC,

8

Prenderei in considerazione lo scripting della tabella o utilizzerei uno strumento di confronto (ad esempio Red Gate) per generare le tabelle nel database di destinazione. Senza indici o vincoli ancora.

Quindi prenderei in considerazione il ripristino del database con un nome diverso sullo stesso server e il fare

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

.. per ogni tabella, con SET IDENTITY INSERT ON se richiesto

Quindi aggiungerei indici e vincoli dopo aver caricato i dati.

Dipende dal tuo livello di comfort con SSIS (la risposta di mrdenny) o se preferisci SQL grezzo.


6

Aggiungerei alla risposta di Mr Denny: scrivere lo schema delle tabelle e poi usare BCP per spostare i dati. Se non hai familiarità con SSIS, utilizzare BCP e i batch dovrebbe essere semplice. Per milioni di righe, niente è meglio di BCP (inserimento in blocco) :).


4

Sono quello che è completamente a disagio con SSIS.

Quando le tabelle di origine non hanno colonne di identità

  1. creare un database vuoto sul server di destinazione
  2. creare un server collegato al server di origine sul server di destinazione
  3. eseguire lo script seguente nel database di origine per generare istruzioni select * in ...
  4. eseguire lo script generato dal database di destinazione
  5. script chiavi primarie, indici, trigger, funzioni e procedure dal database di origine
  6. creare questi oggetti con lo script generato

Ora il T-SQL per generare le istruzioni Select * in ...

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

Questo genera una riga per ogni tabella da copiare come

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

Nel caso in cui le tabelle contengano colonne di identità, scrivo le tabelle includendo proprietà di identità e chiavi primarie.

In questo caso non utilizzo insert in ... select ... utilizzando un server collegato, poiché questa non è una tecnica di massa. Sto lavorando ad alcuni script di PowerShell simili a [questa domanda SO 1 , ma sto ancora lavorando sulla gestione degli errori. Le tabelle veramente grandi possono causare errori di memoria insufficiente, poiché un'intera tabella viene caricata in memoria, prima di essere inviata tramite SQLBulkCopy al database.

La ricreazione di indici ecc. È simile al caso precedente. Questa volta posso saltare la ricreazione delle chiavi primarie.


Nel caso in cui le tabelle contengano colonne di identità, puoi fare come in questa domanda . Ti farà risparmiare un po 'di lavoro manuale. Preferisco ancora batch di inserimenti di massa / SSIS, il server collegato potrebbe non essere una buona soluzione su una vasta rete.
Marian,

1
@Marian Per favore, dai un'occhiata a dba.stackexchange.com/questions/297/… se vuoi promuovere SSIS. Non ho provato SSIS, ma anche Import Export Wizard non è riuscito (oltre al server collegato).
bernd_k,

Avrei aiutato con piacere, ma non ho alcuna scatola Oracle disponibile per me. Ad ogni modo, da quello che sono riuscito a leggere, non ci sono provider che supporteranno Oracle CLOB ..
Marian,

Sono con te su questo: a volte migra i dati, ma non utilizzo mai SSIS.
AK,

2

È possibile utilizzare strumenti di confronto che confrontano schemi e dati di database e sincronizzano prima uno schema di database vuoto con il db originale, per creare tutte le tabelle.

Quindi, sincronizza i dati dal database originale con quello nuovo (tutte le tabelle sono presenti, ma sono tutte vuote) per inserire i record nelle tabelle

Uso ApexSQL Diff e ApexSQL Data Diff per questo, ma ci sono altri strumenti simili.

La cosa positiva di questo processo è che non è necessario sincronizzare effettivamente i database usando lo strumento, poiché questo può essere abbastanza doloroso per milioni di righe.

Puoi semplicemente creare uno script INSERT INTO SQL (non stupirti se si tratta di più concerti) ed eseguirlo.

Poiché script di grandi dimensioni non possono nemmeno essere aperti in SQL Server Management Studio, utilizzo sqlcmd o osql


1

Come menzionato @mrdenny -

  1. eseguire prima lo script delle tabelle con tutti gli indici, gli FK ecc. e creare tabelle vuote nel database di destinazione.

Invece di utilizzare SSIS, utilizzare BCP per inserire dati

  1. bcp i dati usando lo script di seguito. imposta SSMS in modalità testo e copia l'output generato dallo script seguente in un file bat.

    -- 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. Esegui il file bat che genererà i file .dat nella cartella che hai specificato.

  3. Esegui sotto lo script sul

    --- 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. Eseguire l'output utilizzando SSMS per reinserire i dati nelle tabelle.

Questo è un metodo bcp molto veloce in quanto utilizza la modalità nativa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.