SQL Server - saklı yordamları bir veritabanından diğerine kopyalayın


87

SQL'de yeniyim ve yapmam gereken şey 2 .mdf veritabanını tek bir veritabanında birleştirmekti. Bunu SQL Server 2008 Manager - Görevler> Tabloları İçe / Dışa Aktar kullanarak yaptım. Tablolar ve görünümler başarıyla kopyalandı, ancak yeni veritabanında Saklanan prosedürler yok. Bunu yapmanın bir yolu var mı?


1
Bunları programlı olarak kopyalamak istiyorsanız, buradan başlayın: stackoverflow.com/a/6124487/138938
Jon Crowell

Yanıtlar:


138
  • Veritabanına sağ tıklayın
  • Görevler
  • Komut Dosyaları Oluşturun
  • Komut dosyası oluşturmak istediğiniz nesneleri seçin
  • Dosyaya Komut Dosyası
  • Oluşturulan komut dosyalarını hedef veritabanında çalıştırın

Merhaba, hızlı cevap için teşekkürler. Komut dosyasının hedef veritabanına karşı nasıl kullanılacağını açıklar mısınız? Bu işte yeniyim.
Meşe

1
@BarryKaye Ya 30-40 saklanmış prosedürü varsa? Sağ tıklama biraz yavaş olmaz mı?
rvphx

@Oak Oluşturulan Script dosyasını SQL Management Studio'da açın. Bağlantıyı yeni veritabanınızla değiştirin. Veritabanınızda 'VeritabanıAdı Kullan' yazan dosyanın en üstündeki satırı değiştirin ve çalıştırın.
Jaimal Chohan

Vay. Şimdi GUI tabanlı yaklaşımı seven tek kişinin ben olduğumu düşündüm !!
rvphx

10
@RajivVarma - bu görevi veritabanı için bir kez yaparsınız - her bir SP değil! "Depolanan Prosedürler" in yanındaki üst düzey onay kutusunu işaretlerseniz, hepsini birlikte seçer - 1 tıklama.
Barry Kaye

19

Bu kod, Ana veritabanındaki tüm depolanan prosedürleri hedef veritabanına kopyalar, yalnızca istediğiniz prosedürleri prosedür adına göre filtreleyerek kopyalayabilirsiniz.

@sql nvarchar (max) olarak tanımlanır, @Name hedef veritabanıdır

DECLARE c CURSOR FOR 
   SELECT Definition
   FROM [ResiDazeMaster].[sys].[procedures] p
   INNER JOIN [ResiDazeMaster].sys.sql_modules m ON p.object_id = m.object_id

OPEN c

FETCH NEXT FROM c INTO @sql

WHILE @@FETCH_STATUS = 0 
BEGIN
   SET @sql = REPLACE(@sql,'''','''''')
   SET @sql = 'USE [' + @Name + ']; EXEC(''' + @sql + ''')'

   EXEC(@sql)

   FETCH NEXT FROM c INTO @sql
END             

CLOSE c
DEALLOCATE c

Teşekkürler! ... Yorumlarda, ancak kodda belirtilmeyenler @sql& @Name:DECLARE @sql NVARCHAR(MAX); DECLARE @Name NVARCHAR(32);
datalifenyc

Bunu farklı sunucularda yapmanın bir yolu var mı? Sunucu A'dan Sunucu B'ye?
Rajaram1991

5

Geç olan, ancak yararlı olabilecek daha fazla ayrıntı verir ...

İşte avantaj ve dezavantajlarla yapabileceğiniz şeylerin bir listesi

SSMS kullanarak komut dosyaları oluşturun

  • Artıları: kullanımı son derece kolaydır ve varsayılan olarak desteklenir
  • Eksileri: komut dosyaları doğru yürütme sırasında olmayabilir ve ikincil veritabanında saklı yordam zaten varsa hatalar alabilirsiniz. Çalıştırmadan önce komut dosyasını gözden geçirdiğinizden emin olun.

Üçüncü taraf araçlar

  • Artıları: ApexSQL Diff gibi araçlar (benim kullandığım şey budur, ancak Red Gate veya Dev Art'ın araçları gibi birçok başka araç da var) tek bir tıklamayla iki veritabanını karşılaştıracak ve hemen çalıştırabileceğiniz komut dosyası oluşturacak
  • Eksileri: bunlar ücretsiz değil (çoğu satıcının tam işlevsel bir deneme sürümü var)

Sistem Görünümleri

  • Artıları: İkincil sunucuda hangi saklı yordamların bulunduğunu kolayca görebilir ve yalnızca sahip olmadıklarınızı oluşturabilirsiniz.
  • Eksileri: Biraz daha SQL bilgisi gerektirir

Başka bir veritabanında bulunmayan bazı veritabanlarındaki tüm prosedürlerin bir listesini nasıl elde edeceğiniz aşağıda açıklanmıştır.

select *
from DB1.sys.procedures P
where P.name not in 
 (select name from DB2.sys.procedures P2)

5

Başlangıçta bu gönderiyi, depolanmış prosedürleri uzak üretim veritabanımdan yerel geliştirme veritabanıma kopyalamak için bir çözüm arayan buldum. Bu konudaki önerilen yaklaşımı kullanarak başarılı olduktan sonra, giderek tembelleştiğimi (veya hangisini tercih ederseniz edin becerikli olduğumu) fark ettim ve bunun otomatikleştirilmesini istedim. Çok yardımcı olduğu kanıtlanan bu bağlantıya rastladım (teşekkür ederim vincpa) ve onu genişlettim ve aşağıdaki dosya (schema_backup.ps1) ile sonuçlandı:

$server             = "servername"
$database           = "databaseName"
$output_path        = "D:\prod_schema_backup"
$login = "username"
$password = "password"

$schema             = "dbo"
$table_path         = "$output_path\table\"
$storedProcs_path   = "$output_path\stp\"
$views_path         = "$output_path\view\"
$udfs_path          = "$output_path\udf\"
$textCatalog_path   = "$output_path\fulltextcat\"
$udtts_path         = "$output_path\udtt\"

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo")  | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended")  | out-null
$srvConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$srvConn.ServerInstance = $server
$srvConn.LoginSecure = $false
$srvConn.Login = $login
$srvConn.Password = $password
$srv        = New-Object Microsoft.SqlServer.Management.SMO.Server($srvConn)
$db         = New-Object ("Microsoft.SqlServer.Management.SMO.Database")
$tbl        = New-Object ("Microsoft.SqlServer.Management.SMO.Table")
$scripter   = New-Object Microsoft.SqlServer.Management.SMO.Scripter($srvConn)

# Get the database and table objects
$db = $srv.Databases[$database]

$tbl            = $db.tables | Where-object { $_.schema -eq $schema  -and -not $_.IsSystemObject } 
$storedProcs    = $db.StoredProcedures | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject } 
$views          = $db.Views | Where-object { $_.schema -eq $schema } 
$udfs           = $db.UserDefinedFunctions | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject } 
$catlog         = $db.FullTextCatalogs
$udtts          = $db.UserDefinedTableTypes | Where-object { $_.schema -eq $schema } 

# Set scripter options to ensure only data is scripted
$scripter.Options.ScriptSchema  = $true;
$scripter.Options.ScriptData    = $false;

#Exclude GOs after every line
$scripter.Options.NoCommandTerminator   = $false;
$scripter.Options.ToFileOnly            = $true
$scripter.Options.AllowSystemObjects    = $false
$scripter.Options.Permissions           = $true
$scripter.Options.DriAllConstraints     = $true
$scripter.Options.SchemaQualify         = $true
$scripter.Options.AnsiFile              = $true

$scripter.Options.SchemaQualifyForeignKeysReferences = $true

$scripter.Options.Indexes               = $true
$scripter.Options.DriIndexes            = $true
$scripter.Options.DriClustered          = $true
$scripter.Options.DriNonClustered       = $true
$scripter.Options.NonClusteredIndexes   = $true
$scripter.Options.ClusteredIndexes      = $true
$scripter.Options.FullTextIndexes       = $true

$scripter.Options.EnforceScriptingOptions   = $true

function CopyObjectsToFiles($objects, $outDir) {
    #clear out before 
    Remove-Item $outDir* -Force -Recurse
    if (-not (Test-Path $outDir)) {
        [System.IO.Directory]::CreateDirectory($outDir)
    }   

    foreach ($o in $objects) { 

        if ($o -ne $null) {

            $schemaPrefix = ""

            if ($o.Schema -ne $null -and $o.Schema -ne "") {
                $schemaPrefix = $o.Schema + "."
            }

            #removed the next line so I can use the filename to drop the stored proc 
            #on the destination and recreate it
            #$scripter.Options.FileName = $outDir + $schemaPrefix + $o.Name + ".sql"
            $scripter.Options.FileName = $outDir + $schemaPrefix + $o.Name
            Write-Host "Writing " $scripter.Options.FileName
            $scripter.EnumScript($o)
        }
    }
}

# Output the scripts
CopyObjectsToFiles $tbl $table_path
CopyObjectsToFiles $storedProcs $storedProcs_path
CopyObjectsToFiles $views $views_path
CopyObjectsToFiles $catlog $textCatalog_path
CopyObjectsToFiles $udtts $udtts_path
CopyObjectsToFiles $udfs $udfs_path

Write-Host "Finished at" (Get-Date)
$srv.ConnectionContext.Disconnect()

Bunu çağıran ve Görev Zamanlayıcı'dan çağrılan bir .bat dosyam var. Powershell dosyasını aramadan sonra elimde:

for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /Q "DROP PROCEDURE %f"

Bu satır dizinden geçecek ve yeniden oluşturacağı prosedürleri bırakacaktır. Bu bir geliştirme ortamı olmasaydı, prosedürleri bu şekilde programlı olarak bırakmak istemezdim. Daha sonra tüm saklı yordam dosyalarını .sql olacak şekilde yeniden adlandırıyorum:

powershell Dir d:\prod_schema_backup\stp\ | Rename-Item -NewName { $_.name + ".sql" }

Ve sonra çalıştırın:

for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /E /i "%f".sql

Ve bu, tüm .sql dosyalarını yineler ve saklı yordamları yeniden oluşturur. Umarım bunun herhangi bir parçası birine yardımcı olur.


Ben bunu sevdim. Her seferinde bir üretim DB'sinden parçaları arşivlemek için bir işlem yazmam gerekiyor. Şema geliştikçe muhtemelen güncellenmeyecek olan SQL dosyalarına sahip olmak istemiyorum, bu yüzden dosyaları diske yazma ara adımı olmadan bir hedefe dayalı boş bir DB oluşturmak için bunu uyarlıyorum (daha fazlası temizlemek). Sanırım bu, bu soru için muhtemelen en iyi ve en çok tekrar kullanılabilir cevap, tebrikler efendim!
Steve Pettifer

3

Aktarmanız gereken her şeyi komut dosyası oluşturmak için SSMS'nin "Komut Dosyası Oluştur ..." işlevini kullanabilirsiniz. SSMS'de kaynak veritabanına sağ tıklayın, "Komut Dosyaları Oluştur ..." seçeneğini seçin ve sihirbazı izleyin. Ardından, depolanan yordam oluşturma ifadelerini içerecek olan sonuç komut dosyanızı çalıştırın.


3

kullanım

select * from sys.procedures

tüm prosedürlerinizi göstermek için;

sp_helptext @objname = 'Procedure_name'

kodu almak için

ve hepsinden geçip dışa aktarma kodunu oluşturmak için bir şeyler oluşturma yaratıcılığınız :)


3

Diğer yanıtlarda gösterildiği gibi depolanan işlemlerin komut dosyasını oluşturabilirsiniz. Komut dosyası oluşturulduktan sonra, sqlcmdbunları hedef DB'ye karşı çalıştırmak için kullanabilirsiniz .

sqlcmd -S <server name> -U <user name> -d <DB name> -i <script file> -o <output log file> 

0

Mgmt Studio'da, orijinal veritabanınıza sağ tıklayın, ardından Görevler'e ve ardından Komut Dosyaları Oluştur ... - sihirbazı izleyin.


0

SEÇİN tanım + char (13) + MyDatabase.sys.sql_modules s INNER JOIN MyDatabase.sys.procedures p ON [s]. [Object_id] = [p]. [Object_id] p.name GİBİ 'Something% '"sorgu" c: \ SP_scripts.sql -S MyInstance -T -t -w

sp'yi alın ve çalıştırın


Bu çok güzel bir çözüm, ancak 1) metin veya dosya çıktısının gerekli olduğunu belirtmelisiniz (sonuçları kılavuzda göstermeyin, yoksa EOL karakterlerini kaybedersiniz) ve 2) 8k sınırı var gibi görünüyor SQL Server Management stüdyosunda metin çıktısı için.
DAB

0

Diğer bir seçenek de, SQL Server Integration Services (SSIS) kullanarak depolanan prosedürleri aktarmaktır . SQL Sunucu Nesnelerini Aktar Görevi adlı bir görev vardır . Görevi aşağıdaki öğeleri aktarmak için kullanabilirsiniz:

  • Tablolar
  • Görüntüleme
  • Saklanan Prosedürler
  • Kullanıcı Tanımlı İşlevler
  • Varsayılanlar
  • Kullanıcı Tanımlı Veri Türleri
  • Bölme İşlevleri
  • Bölüm Şemaları
  • Şemalar
  • Meclisler
  • Kullanıcı Tanımlı Toplamalar
  • Kullanıcı Tanımlı Türler
  • XML Şema Koleksiyonu

Bu bir var grafiksel öğretici SQL Server Objects Görev Transferi için.

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.