Memindahkan tabel ke database SQL2008 lainnya (termasuk indeks, pemicu, dll.)

16

Saya perlu memindahkan sejumlah besar (100+) besar (jutaan baris) tabel dari satu database SQL2008 ke yang lain.

Saya awalnya hanya menggunakan Wisaya Impor / Ekspor, tetapi semua tabel tujuan tidak memiliki kunci utama dan asing, indeks, batasan, pemicu, dll. (Kolom identitas juga dikonversi ke INT sederhana, tapi saya pikir saya baru saja melewatkan kotak centang di Penyihir.)

Apa cara yang benar untuk melakukan ini?

Jika ini hanya beberapa tabel, saya akan kembali ke sumber, skrip definisi tabel (dengan semua indeks, dll), kemudian jalankan bagian pembuatan indeks skrip pada tujuan. Tetapi dengan begitu banyak tabel, ini tampaknya tidak praktis.

Jika tidak ada begitu banyak data, saya bisa menggunakan wizard "Buat Skrip ..." untuk skrip sumber, termasuk data, tetapi skrip baris 72m sepertinya bukan ide yang bagus!

BradC
sumber
Dan tidak semua tabel dalam database?
thursdaysgeek
@thursdaysgeek: Hampir semua tabelnya, tetapi database tujuan sudah memiliki lebih dari 100 tabel. Jadi, hanya memulihkan dari cadangan dengan nama yang berbeda bukanlah suatu pilihan. Pikirkan ini sebagai dasarnya "menggabungkan dua database besar ini bersama-sama".
BradC

Jawaban:

14

Membuat skrip tabel, kemudian menggunakan SSIS untuk mentransfer data akan menjadi cara yang paling dapat diandalkan dan efektif untuk memindahkan data ke database baru.

mrdenny
sumber
9

Kami benar-benar melakukannya menggunakan banyak skrip manual dalam hubungannya dengan panduan Impor, tetapi pagi ini saya menemukan jawaban yang lebih baik, milik artikel blog Tibor Karaszi .

Bagian dari frustrasi kami di sini adalah bahwa SQL 2000 "DTS Import / Export Wizard" sebenarnya membuat ini hampir sepele dengan memilih "Copy Objects and Data":

Wisaya Impor DTS

Opsi ketiga ini adalah yang berisi kemampuan untuk memasukkan indeks / pemicu, dll:

Opsi Tingkat Lanjut

Opsi ini DIHAPUS dari Wisaya Impor SQL 2005/2008 . Mengapa? Tidak ada ide:

Wisaya Impor 2008

Pada 2005/2008, Anda tampaknya harus secara manual membuat paket SSIS di BIDS dan menggunakan Transfer SQL Server Objects Task , yang berisi semua opsi yang sama yang ada di panduan 2000:

SSIS Mentransfer Tugas Objek SQL Server

BradC
sumber
Hanya ingin memposting bahwa saya menggunakan metode SSIS ini untuk tugas serupa lainnya, dan itu berhasil!
BradC
8

Saya akan mempertimbangkan untuk menuliskan tabel, atau menggunakan alat perbandingan (misalnya Gerbang Merah) untuk menghasilkan tabel dalam database target. Belum ada indeks atau kendala.

Lalu saya akan mempertimbangkan memulihkan database dengan nama yang berbeda dan melakukan di server yang sama

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

.. untuk setiap tabel, dengan SET IDENTITAS INSERT AKTIF jika diminta

Lalu saya akan menambahkan indeks dan batasan setelah memuat data.

Itu tergantung pada tingkat kenyamanan Anda dengan SSIS (jawaban mrdenny) atau jika Anda lebih suka SQL mentah.

gbn
sumber
6

Saya akan menambahkan jawaban Tn. Denny: Tuliskan skema tabel lalu gunakan BCP untuk memindahkan data. Jika Anda tidak terbiasa dengan SSIS, maka menggunakan BCP dan batch harus mudah dilakukan. Untuk jutaan baris, tidak ada yang mengalahkan BCP (masukkan massal) :).

Marian
sumber
4

Saya orang yang benar-benar tidak nyaman dengan SSIS.

Ketika tabel sumber tidak memiliki kolom identitas

  1. buat database kosong di server target
  2. buat server tertaut ke server sumber pada server target
  3. jalankan skrip di bawah ini pada basis data sumber untuk menghasilkan pernyataan * pilih ke ...
  4. jalankan skrip yang dihasilkan dari database target
  5. skrip kunci utama, indeks, pemicu, fungsi dan prosedur dari sumber database
  6. buat objek-objek ini dengan skrip yang dihasilkan

Sekarang T-SQL untuk menghasilkan pernyataan Select * into ...

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

Ini menghasilkan garis untuk setiap tabel untuk menyalin suka

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

Dalam hal tabel berisi kolom identitas, saya skrip tabel termasuk properti identitas dan kunci utama.

Saya tidak menggunakan masukkan ke ... pilih ... menggunakan server yang terhubung dalam hal ini, karena ini bukan teknik massal. Saya sedang mengerjakan beberapa skrip PowerShell yang mirip dengan [pertanyaan SO 1 ini , tapi saya masih mengerjakan penanganan kesalahan. Tabel yang benar-benar besar dapat menyebabkan kesalahan memori, karena seluruh tabel dimuat ke dalam memori, sebelum dikirim melalui SQLBulkCopy ke database.

Rekreasi indeks dll. Mirip dengan kasus di atas. Kali ini saya dapat melewatkan rekreasi dari kunci utama.

bernd_k
sumber
Jika tabel berisi kolom identitas, Anda dapat melakukannya seperti dalam pertanyaan ini . Ini akan menghemat beberapa pekerjaan manual. Saya masih lebih suka memasukkan batch massal / SSIS, server yang terhubung mungkin bukan solusi yang baik melalui jaringan yang luas.
Marian
1
@Marian Silakan lihat di dba.stackexchange.com/questions/297/… jika Anda ingin mempromosikan SSIS. Saya tidak mencoba SSIS, tetapi Impor Ekspor Wizard gagal juga (selain server yang ditautkan).
bernd_k
Saya akan membantu dengan senang hati, tetapi saya tidak memiliki kotak Oracle yang tersedia untuk saya. Ngomong-ngomong, dari apa yang saya baca, tidak ada penyedia yang akan mendukung Oracle CLOB ..
Marian
Saya bersama Anda dalam hal ini - kadang-kadang saya melakukan migrasi data, tetapi tidak pernah menggunakan SSIS.
AK
2

Anda dapat menggunakan alat perbandingan yang membandingkan skema dan data basis data dan pertama-tama menyinkronkan blank skema database dengan db asli, untuk membuat semua tabel.

Kemudian, sinkronkan data dari database asli dengan yang baru (semua tabel ada di sana, tetapi semuanya kosong) untuk menyisipkan rekaman ke dalam tabel

Saya menggunakan ApexSQL Diff dan ApexSQL Data Diff untuk ini, tetapi ada alat serupa lainnya.

Hal yang baik tentang proses ini adalah Anda tidak harus benar-benar menyinkronkan basis data menggunakan alat ini, karena ini bisa sangat menyakitkan bagi jutaan baris.

Anda bisa membuat skrip INSERT INTO SQL (jangan kaget jika beberapa gigs) dan jalankan.

Karena skrip yang begitu besar bahkan tidak dapat dibuka di SQL Server Management Studio, saya menggunakan sqlcmd atau osql

Carol Baker Barat
sumber
1

Seperti yang disebutkan @rdenny -

  1. skrip tabel pertama dengan semua Indeks, FK, dll dan buat tabel kosong di database tujuan.

Alih-alih menggunakan SSIS, gunakan BCP untuk memasukkan data

  1. bcp keluar data menggunakan skrip di bawah ini. atur SSMS dalam Mode Teks dan salin output yang dihasilkan oleh skrip di bawah ini dalam 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. Jalankan file bat yang akan menghasilkan file dat di folder yang telah Anda tentukan.

  3. Jalankan skrip di bawah ini di

    --- 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. Jalankan output menggunakan SSMS untuk memasukkan kembali data dalam tabel.

Ini adalah metode bcp yang sangat cepat karena menggunakan mode Asli.

Kin Shah
sumber