Tabloları başka bir SQL2008 veritabanına taşıma (dizinler, tetikleyiciler vb. Dahil)


16

Bir demet (100 +) büyük (milyonlarca satır) tabloları bir SQL2008 veritabanından diğerine taşımak gerekiyor.

Başlangıçta sadece Alma / Verme Sihirbazı'nı kullandım, ancak tüm hedef tablolarda birincil ve yabancı anahtarlar, dizinler, kısıtlamalar, tetikleyiciler vb. Eksikti. (Kimlik sütunları da düz INT'lere dönüştürüldü, ancak sanırım sihirbazı.)

Bunu yapmanın doğru yolu nedir?

Bu sadece birkaç tablo olsaydı, kaynağa geri gider, tablo tanımını (tüm dizinlerle vb.) Dışarı çıkarır, sonra komut dosyasının dizin oluşturma bölümlerini çalıştırırdım. Ancak birçok tablo ile bu pratik değildir.

Çok fazla veri olmasaydı, veri de dahil olmak üzere kaynak komut dosyası oluşturmak için "Komut Dosyaları Oluştur ..." sihirbazını kullanabilirdim, ancak 72 metrelik bir komut dosyası iyi bir fikir gibi görünmüyor!


Ve veritabanındaki tüm tablolar değil mi?
thursdaysgeek

@ thursdaysgeek: Neredeyse tüm tabloları, ancak hedef veritabanında zaten 100'den fazla tablo var. Bu yüzden sadece farklı bir adla yedeklemeden geri yükleme bir seçenek değildir. Bunu temelde "bu iki büyük veritabanını birleştirin" olarak düşünün.
BradC

Yanıtlar:


14

Tabloları komut dosyası haline getirmek, ardından verileri aktarmak için SSIS kullanmak, verileri yeni veritabanına taşımanın en güvenilir ve etkili yolu olacaktır.


9

Aslında İthalat sihirbazı ile birlikte çok sayıda manuel komut dosyası kullanarak yaptık, ancak bu sabah Tibor Karaszi'nin blog makalesinin izniyle daha iyi bir cevap buldum .

Buradaki hayal kırıklığımızın bir parçası, SQL 2000 "DTS Alma / Verme Sihirbazı" nın aslında "Nesneleri ve Verileri Kopyala" yı seçerek bunu neredeyse önemsiz bir şekilde kolaylaştırmasıydı:

DTS Alma Sihirbazı

Bu üçüncü seçenek, dizin / tetikleyici vb. Ekleme yeteneğini içeren seçenektir:

Gelişmiş seçenekler

Bu seçenek oldu KALDIRILDI gelen SQL 2005/2008 Alma Sihirbazı. Neden? Fikrim yok:

2008 Alma Sihirbazı

2005 / 2008'de, görünüşe göre BIDS'te manuel olarak bir SSIS paketi oluşturmanız ve 2000 sihirbazındaki tüm seçenekleri içeren SQL Server Nesnelerini Aktar Görevini kullanmanız gerekir :

SSIS Aktarım SQL Server Nesneleri Görevi


Başka bir benzer görev için bu SSIS yöntemini kullandığımı söylemek istedim ve harika çalıştı!
BradC

8

Tablo komut dosyası dışarı düşünmek veya hedef veritabanında tablolar oluşturmak için bir karşılaştırma araçları (örneğin Red Gate) kullanın. Henüz dizinler veya kısıtlamalar olmadan.

Sonra aynı sunucuda farklı bir adla veritabanını geri yükleme ve

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

.. her tablo için, gerekirse İDARİ KİMLİĞİ TAKIN

Sonra veri yükledikten sonra dizinler ve kısıtlamalar eklemek istiyorum.

SSIS (mrdenny'nin cevabı) veya ham SQL'i tercih ederseniz konfor seviyenize bağlıdır.


6

Bay Denny'nin cevabına ekliyorum: Tablolar şemasını komut dosyası haline getirdikten sonra verileri taşımak için BCP'yi kullanın. SSIS'e aşina değilseniz, BCP ve partileri kullanmak kolay olmalıdır. Milyonlarca satır için hiçbir şey BCP'yi (toplu ekleme) geçemez :).


4

SSIS'den tamamen rahatsız olan benim.

Kaynak tablolarda kimlik sütunu olmadığında

  1. hedef sunucuda boş bir veritabanı oluşturmak
  2. hedef sunucudaki kaynak sunucuya bağlı bir sunucu oluşturma
  3. select * into ... ifadeleri oluşturmak için kaynak veritabanında aşağıdaki komut dosyasını çalıştırın
  4. oluşturulan veritabanını hedef veritabanından çalıştır
  5. birincil veritabanını, dizinleri, tetikleyicileri, işlevleri ve yordamları kaynak veritabanından komut dosyası
  6. bu nesneleri oluşturulan komut dosyasıyla oluştur

Şimdi T-SQL Select * into ... ifadeleri üretecek

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

Bu, kopyalanacak her tablo için bir satır oluşturur

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

Tabloların kimlik sütunları içermesi durumunda, kimlik özelliği ve birincil anahtarlar da dahil olmak üzere tabloları kodlarım.

Bu durumda bağlantılı bir sunucu kullanarak ... select ... içine insert kullanmıyorum, çünkü bu toplu bir teknik değildir. [Bu SO soru 1 benzer bazı PowerShell komut dosyaları üzerinde çalışıyorum , ancak hala hata işleme üzerinde çalışıyorum. Gerçekten büyük tablolar, SQLBulkCopy aracılığıyla veritabanına gönderilmeden önce bir tablonun tamamı belleğe yüklendiği için bellek hatalarına neden olabilir.

Endekslerin rekreasyonu vb. Yukarıdaki duruma benzer. Bu sefer birincil anahtarların yeniden oluşturulmasını atlayabilirim.


Tablolarda kimlik sütunları varsa, bu soruya benzer şekilde yapabilirsiniz . Size bazı manuel çalışmalardan tasarruf sağlayacaktır. Ben hala toplu insert toplu / SSIS tercih, bağlantılı sunucu geniş bir ağ üzerinde iyi bir çözüm olmayabilir.
Marian

1
@Marian SSIS'i tanıtmak istiyorsanız lütfen dba.stackexchange.com/questions/297/… adresine bakın . SSIS'yi denemedim, ancak İçe Aktarma Dışa Aktarma Sihirbazı da (bağlantılı sunucunun yanı sıra) başarısız oldu.
bernd_k

Memnuniyetle yardım ederdim, ancak kullanabileceğim bir Oracle kutum yok. Her neyse, okumayı başardığımdan, Oracle CLOB'u destekleyecek hiçbir sağlayıcı yok ..
Marian

Bu konuda seninleyim - bazen veri taşıyorum ama asla SSIS kullanmıyorum.
AK

2

Tüm tabloları oluşturmak için veritabanı şemalarını ve verileri karşılaştıran ve boş bir veritabanı şemasını orijinal db ile eşitleyen karşılaştırma araçlarını kullanabilirsiniz .

Daha sonra, kayıtları tablolara eklemek için orijinal veritabanındaki verileri yenisiyle senkronize edin (tüm tablolar oradadır, ancak hepsi boştur)

Bunun için ApexSQL Diff ve ApexSQL Data Diff kullanıyorum , ancak başka benzer araçlar da var.

Bu işlemle ilgili iyi olan şey, aracı kullanarak veritabanlarını gerçekten senkronize etmeniz gerekmemesidir, çünkü bu milyonlarca satır için oldukça acı verici olabilir.

Sadece bir INSERT INTO SQL betiği oluşturabilir (birkaç konser ise şaşırmayın) ve yürütebilirsiniz.

SQL Server Management Studio'da bile büyük komut dosyaları açılamadığından sqlcmd veya osql kullanıyorum


1

@Mrdenny'nin de belirttiği gibi -

  1. önce tüm Dizinler, FK'ler vb.İle tablolar oluşturun ve hedef veritabanında boş tablolar oluşturun.

SSIS kullanmak yerine, veri eklemek için BCP'yi kullanın

  1. bcp aşağıdaki komut dosyasını kullanarak veri dışarı. Metin Modunda SSMS'yi ayarlayın ve aşağıdaki komut dosyası tarafından üretilen çıktıyı bir yarasa dosyasına kopyalayın.

    -- 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. Belirttiğiniz klasörde .dat dosyalarını oluşturacak yarasa dosyasını çalıştırın.

  3. Aşağıdaki komut dosyasını çalıştırın

    --- 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. Tablolara veri eklemek için SSMS'yi kullanarak çıktıyı çalıştırın.

Bu, Native modunu kullandığından çok hızlı bir bcp yöntemidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.