SQL Server - salin prosedur yang tersimpan dari satu db ke db lainnya

87

Saya baru mengenal SQL, dan yang perlu saya lakukan adalah menggabungkan 2 database .mdf menjadi satu. Saya melakukan itu menggunakan SQL Server 2008 Manager - Tugas> Impor / Ekspor tabel. Tabel dan tampilan berhasil disalin, tetapi tidak ada prosedur Tersimpan di database baru. Apakah ada cara untuk melakukannya?

ek
sumber
1
Jika Anda ingin menyalinnya secara terprogram, mulai di sini: stackoverflow.com/a/6124487/138938
Jon Crowell

Jawaban:

138
  • Klik kanan pada database
  • Tugas
  • Hasilkan Skrip
  • Pilih objek yang ingin Anda skrip
  • Script ke File
  • Jalankan skrip yang dihasilkan terhadap database target
Jaimal Chohan
sumber
Hai, terima kasih atas balasan cepatnya. Bisakah Anda menjelaskan cara menggunakan skrip terhadap database target. Saya baru dalam hal ini.
Oak
1
@BarryKaye Bagaimana jika dia memiliki 30-40 prosedur yang tersimpan? Bukankah mengklik kanan akan sedikit lambat?
rvphx
@Oak Buka menghasilkan file Script di SQL Management Studio. Ubah koneksi ke database baru Anda. Ubah baris di bagian paling atas file yang bertuliskan 'Use DatabaseName' ke database Anda dan jalankan.
Jaimal Chohan
Wow. Sekarang saya berpikir bahwa saya adalah satu-satunya yang menyukai pendekatan berbasis GUI !!
rvphx
10
@RajivVarma - Anda melakukan tugas ini sekali untuk database - bukan setiap SP! Jika Anda mencentang kotak centang tingkat atas di samping "Prosedur Tersimpan" itu memilih semuanya bersama - 1 klik.
Barry Kaye
19

Kode ini menyalin semua prosedur yang tersimpan dalam database Master ke database target, Anda dapat menyalin hanya prosedur yang Anda suka dengan memfilter kueri pada nama prosedur.

@sql didefinisikan sebagai nvarchar (max), @Name adalah database target

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
ShaQue
sumber
Terima kasih! ... Di komentar, tetapi tidak dinyatakan dalam kode adalah @sql& @Name:DECLARE @sql NVARCHAR(MAX); DECLARE @Name NVARCHAR(32);
datalifenyc
Apakah ada cara untuk melakukan hal yang sama di server yang berbeda? Dari Server A Ke Server B?
Rajaram1991
5

Terlambat tetapi memberikan lebih banyak detail yang mungkin berguna ...

Berikut adalah daftar hal-hal yang dapat Anda lakukan dengan kelebihan dan kekurangan

Buat skrip menggunakan SSMS

  • Kelebihan: sangat mudah digunakan dan didukung secara default
  • Kekurangan: skrip mungkin tidak dalam urutan eksekusi yang benar dan Anda mungkin mendapatkan kesalahan jika prosedur tersimpan sudah ada di database sekunder. Pastikan Anda meninjau skrip sebelum menjalankan.

Alat pihak ketiga

  • Kelebihan: alat seperti ApexSQL Diff (ini yang saya gunakan tetapi ada banyak alat lain seperti dari Red Gate atau Dev Art) akan membandingkan dua database dalam satu klik dan menghasilkan skrip yang dapat Anda jalankan segera
  • Kekurangan: ini tidak gratis (meskipun sebagian besar vendor memiliki uji coba yang berfungsi penuh)

Tampilan Sistem

  • Kelebihan: Anda dapat dengan mudah melihat prosedur tersimpan yang ada di server sekunder dan hanya menghasilkan yang tidak Anda miliki.
  • Kekurangan: Membutuhkan lebih banyak pengetahuan SQL

Berikut adalah cara mendapatkan daftar semua prosedur di beberapa database yang tidak ada di database lain

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

Saya awalnya menemukan posting ini mencari solusi untuk menyalin prosedur yang tersimpan dari database produksi jarak jauh saya ke database pengembangan lokal saya. Setelah berhasil menggunakan pendekatan yang disarankan di utas ini, saya menyadari bahwa saya semakin malas (atau banyak akal, mana pun yang Anda suka) dan ingin ini otomatis. Saya menemukan tautan ini , yang terbukti sangat membantu (terima kasih vincpa), dan saya memperpanjangnya, menghasilkan file berikut (schema_backup.ps1):

$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()

Saya memiliki file .bat yang memanggil ini, dan dipanggil dari Penjadwal Tugas. Setelah panggilan ke file Powershell, saya memiliki:

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

Baris itu akan melewati direktori dan menjatuhkan prosedur yang akan dibuat ulang. Jika ini bukan lingkungan pengembangan, saya tidak ingin menghentikan prosedur secara terprogram dengan cara ini. Saya kemudian mengganti nama semua file prosedur tersimpan menjadi .sql:

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

Dan kemudian jalankan:

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

Dan itu mengulang melalui semua file .sql dan membuat ulang prosedur yang tersimpan. Saya berharap bahwa bagian mana pun dari ini akan terbukti bermanfaat bagi seseorang.

vandsh
sumber
Saya menyukai ini. Saya harus menulis proses untuk mengarsipkan potongan dari DB produksi satu tahun pada satu waktu. Saya tidak ingin memiliki file SQL yang menggantung yang mungkin tidak akan diperbarui saat skema berkembang jadi saya mengadaptasi ini untuk membuat DB kosong berdasarkan target tanpa langkah perantara menulis file ke disk (selengkapnya membersihkan). Saya rasa ini mungkin jawaban terbaik dan paling dapat digunakan untuk pertanyaan ini, pujian pak!
Steve Pettifer
3

Anda dapat menggunakan fungsi "Hasilkan Skrip ..." SSMS untuk membuat skrip apa pun yang perlu Anda transfer. Klik kanan pada database sumber di SSMS, pilih "Generate Scripts ...", dan ikuti wizard. Kemudian jalankan skrip resultan Anda yang sekarang akan berisi pernyataan pembuatan prosedur tersimpan.

bluevector.dll
sumber
3

menggunakan

select * from sys.procedures

untuk menunjukkan semua prosedur Anda;

sp_helptext @objname = 'Procedure_name'

untuk mendapatkan kodenya

dan kreativitas Anda untuk membangun sesuatu untuk mengulang semuanya dan menghasilkan kode ekspor :)

Diego
sumber
3

Anda dapat membuat skrip dari proc yang disimpan seperti yang digambarkan dalam jawaban lain. Setelah skrip dibuat, Anda dapat menggunakannya sqlcmduntuk mengeksekusinya terhadap DB target seperti

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

Di Mgmt Studio, klik kanan database asli Anda, lalu Tasks, lalu Generate Scripts ... - ikuti wizard.

Barry Kaye
sumber
0

PILIH definisi + char (13) + 'GO' FROM MyDatabase.sys.sql_modules s INNER JOIN MyDatabase.sys.procedures p ON [s]. [Object_id] = [p]. [Object_id] DI MANA p.name LIKE 'Something% '"queryout" c: \ SP_scripts.sql -S MyInstance -T -t -w

dapatkan sp dan jalankan

ShaQue
sumber
Ini adalah solusi yang sangat bagus, tetapi 1) Anda harus menunjukkan bahwa teks atau keluaran file diperlukan (jangan tampilkan hasilnya di kisi, atau Anda akan kehilangan karakter EOL) dan 2) tampaknya ada batas 8k untuk keluaran teks di studio Manajemen Server SQL.
DAB
0

Pilihan lainnya adalah mentransfer prosedur tersimpan menggunakan SQL Server Integration Services (SSIS) . Ada tugas yang disebut Tugas Transfer SQL Server Objects . Anda dapat menggunakan tugas untuk mentransfer item berikut:

  • Tabel
  • Tampilan
  • Prosedur Tersimpan
  • Fungsi Buatan Pengguna
  • Default
  • Jenis Data Buatan Pengguna
  • Fungsi Partisi
  • Skema Partisi
  • Skema
  • Sidang
  • Agregat Buatan Pengguna
  • Jenis yang Ditentukan Pengguna
  • Koleksi Skema XML

Ini adalah tutorial grafis untuk Transfer SQL Server Objects Task.

Abdollah
sumber