it-swarm-eu.dev

Přesouvání tabulek do jiné databáze SQL2008 (včetně indexů, triggerů atd.)

Potřebuji přesunout celou hromadu (100+) velkých (miliony řádků) tabulek z jedné databáze SQL2008 do druhé.

Původně jsem použil Průvodce importem/exportem, ale ve všech cílových tabulkách chyběly primární a cizí klíče, indexy, omezení, triggery atd. (Sloupce identity byly také převedeny na obyčejné INTs, ale myslím, že jsem právě zmeškal zaškrtávací políčko v kouzelník.)

Jaký je správný způsob, jak toho dosáhnout?

Pokud by to bylo jen pár tabulek, vrátil bych se ke zdroji, skriptoval definici tabulky (se všemi indexy atd.) A potom spustil části skriptu pro vytvoření indexu v cíli. Ale s tolika tabulkami se to zdá nepraktické.

Pokud by nebylo tolik dat, mohl bych pomocí průvodce „Vytvořit skripty ...“ skriptovat zdroj, včetně dat, ale 72m řádkový skript prostě nevypadá jako dobrý nápad!

16
BradC

Vlastně jsme to provedli pomocí mnoha ručních skriptů ve spojení s Průvodcem importem, ale dnes ráno jsem našel lepší odpověď s laskavým svolením článek blogu Tibora Karasziho .

Část naší frustrace zde spočívala v tom, že SQL 2000 „Průvodce importem/exportem DTS“ to ve skutečnosti téměř usnadňuje výběrem možnosti „Kopírovat objekty a data“:

DTS Import Wizard

Tato třetí možnost je ta, která obsahuje možnost zahrnout indexy/triggery atd.:

Advanced Options

Tato možnost byla [~ # ~] odstraněna [~ # ~] z SQL 2005/2008 Průvodce importem. Proč? Žádný nápad:

2008 Import Wizard

V roce 2005/2008 musíte zřejmě ručně vytvořit balíček SSIS v BIDS a použít Transfer SQL Server Objects Task , který obsahuje všechny stejné možnosti, jaké byly v průvodce 2000:

SSIS Transfer SQL Server Objects Task

9
BradC

Nejspolehlivějším a nejefektivnějším způsobem přesunu dat do nové databáze by bylo skriptování tabulek a použití SSIS k přenosu dat.

14
mrdenny

Zvažoval bych skriptovat tabulku ven, nebo použít porovnávací nástroje (např. Red Gate) k vygenerování tabulek v cílové databázi. Bez indexů nebo omezení dosud.

Pak bych uvažoval o obnovení databáze s jiným jménem na stejném serveru a provedení

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

.. pro každou tabulku, se SET IDENTITY INSERT ON V případě potřeby

Poté bych po načtení dat přidal indexy a omezení.

Závisí to na vaší úrovni komfortu s SSIS (mrdennyho odpověď), nebo pokud dáváte přednost surovému SQL.

8
gbn

Chtěl bych přidat k odpovědi pana Dennyho: Script out the tables schéma potom pomocí BCP přesunout data. Pokud nejste obeznámeni s SSIS, pak by mělo být snadné používat BCP a šarže. Pro miliony řádků nic nepřekonává BCP (hromadné vložení) :).

6
Marian

Já jsem ten, kdo je s SSIS úplně nepříjemný.

Když zdrojové tabulky nemají žádné sloupce identity

  1. vytvořit prázdnou databázi na cílovém serveru
  2. vytvořit propojený server se zdrojovým serverem na cílovém serveru
  3. spusťte skript níže ve zdrojové databázi a vygenerujte příkazy * do ... příkazů
  4. spusťte vygenerovaný skript z cílové databáze
  5. skriptové primární klíče, indexy, spouštěče, funkce a procedury ze zdrojové databáze
  6. vytvořte tyto objekty generovaným skriptem

T-SQL nyní generuje příkazy Select * do ...

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

Tím se pro každou tabulku vytvoří řádek, který se má zkopírovat

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

V případě, že tabulky obsahují sloupce identity, skriptuji tabulky včetně vlastnosti identity a primárních klíčů.

Nepoužívám vložení do ... select ... v tomto případě pomocí propojeného serveru, protože nejde o hromadnou techniku. Pracuji na některých skriptech PowerShell podobných [této SO otázka 1 , ale stále pracuji na zpracování chyb. Opravdu velké tabulky mohou způsobit nedostatek paměti chyby, protože celá tabulka je načtena do paměti před jejím odesláním přes SQLBulkCopy do databáze.

Rekreace indexů atd. Je podobná jako v předchozím případě. Tentokrát mohu přeskočit rekreaci primárních klíčů.

4
bernd_k

K vytvoření všech tabulek můžete použít srovnávací nástroje, které porovnají schémata a data databáze a nejprve synchronizují prázdné schéma databáze s původním db.

Poté synchronizujte data z původní databáze s novou (všechny tabulky jsou tam, ale všechny jsou prázdné) a vložte záznamy do tabulek

K tomu používám ApexSQL Diff a ApexSQL Data Diff , ale existují i ​​jiné podobné nástroje.

Dobrá věc na tomto procesu je, že nemusíte skutečně synchronizovat databáze pomocí nástroje, protože to může být docela bolestivé pro miliony řádků.

Můžete pouze vytvořit skript INSERT INTO SQL (nenechte se překvapit, pokud je to několik koncertů) a spusťte jej.

Protože tak velké skripty nelze otevřít ani v SQL Server Management Studio, používám sqlcmd nebo osql

2
Carol Baker West

Jak @mrdenny zmínil -

  1. nejprve skriptujte tabulky se všemi indexy, FK, atd. a vytvořte prázdné tabulky v cílové databázi.

Namísto použití SSIS použijte k vložení dat BCP

  1. bcp z dat pomocí skriptu níže. nastavte SSMS v textovém režimu a zkopírujte výstup generovaný skriptem do souboru 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. Spusťte soubor bat, který vygeneruje soubory .dat ve složce, kterou jste určili.

  3. Spustit pod skript na

    --- 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. Spusťte výstup pomocí SSMS pro vložení dat zpět do tabulek.

Toto je velmi rychlá metoda BCP, protože používá nativní režim.

1
Kin Shah