SQL Server - sao chép các thủ tục được lưu trữ từ db này sang db khác


86

Tôi mới làm quen với SQL và điều tôi cần làm là kết hợp 2 cơ sở dữ liệu .mdf thành một. Tôi đã làm điều đó bằng cách sử dụng Trình quản lý SQL Server 2008 - Tác vụ> Nhập / Xuất bảng. Các bảng và dạng xem đã được sao chép thành công, nhưng không có thủ tục được lưu trữ trong cơ sở dữ liệu mới. Có cách nào để làm điều đó?


1
Nếu bạn muốn sao chép chúng theo chương trình, hãy bắt đầu tại đây: stackoverflow.com/a/6124487/138938
Jon Crowell

Câu trả lời:


137
  • Nhấp chuột phải vào cơ sở dữ liệu
  • Nhiệm vụ
  • Tạo tập lệnh
  • Chọn các đối tượng bạn muốn viết kịch bản
  • Tập lệnh vào tệp
  • Chạy các tập lệnh đã tạo dựa trên cơ sở dữ liệu đích

Xin chào, cảm ơn vì đã trả lời nhanh. Bạn có thể vui lòng giải thích cách sử dụng script chống lại cơ sở dữ liệu đích. Tôi mới làm quen với điều này.
Oak

1
@BarryKaye Điều gì sẽ xảy ra nếu anh ta có 30-40 thủ tục được lưu trữ? Nhấp chuột phải sẽ không chậm một chút?
rvphx

@Oak Mở tệp Script tạo trong SQL Management Studio. Thay đổi Kết nối thành cơ sở dữ liệu mới của bạn. Thay đổi dòng ở đầu tệp có nội dung 'Sử dụng tên cơ sở dữ liệu' cho cơ sở dữ liệu của bạn và thực thi.
Jaimal Chohan

Chà. Bây giờ tôi nghĩ rằng tôi là người duy nhất thích cách tiếp cận dựa trên GUI !!
rvphx

10
@RajivVarma - bạn thực hiện tác vụ này một lần cho cơ sở dữ liệu - không phải từng SP! Nếu bạn đánh dấu vào hộp kiểm cấp cao nhất bên cạnh "Thủ tục được lưu trữ", nó sẽ chọn tất cả chúng lại với nhau - 1 lần nhấp.
Barry Kaye

19

Mã này sao chép tất cả các thủ tục được lưu trữ trong cơ sở dữ liệu Master sang cơ sở dữ liệu đích, bạn có thể chỉ sao chép các thủ tục bạn thích bằng cách lọc truy vấn về tên thủ tục.

@sql được định nghĩa là nvarchar (max), @Name là cơ sở dữ liệu đích

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

Cảm ơn! ... Trong các bình luận, nhưng không được khai báo trong mã là @sql& @Name:DECLARE @sql NVARCHAR(MAX); DECLARE @Name NVARCHAR(32);
datalifenyc

Có cách nào để làm điều này tương tự trong các máy chủ khác nhau không? Từ Máy chủ A đến Máy chủ B?
Rajaram1991

5

Muộn hơn nhưng cung cấp thêm thông tin chi tiết có thể hữu ích…

Dưới đây là danh sách những điều bạn có thể làm với những thuận lợi và khó khăn

Tạo tập lệnh bằng SSMS

  • Ưu điểm: cực kỳ dễ sử dụng và được hỗ trợ theo mặc định
  • Nhược điểm: các tập lệnh có thể không theo đúng thứ tự thực thi và bạn có thể gặp lỗi nếu thủ tục được lưu trữ đã tồn tại trên cơ sở dữ liệu thứ cấp. Đảm bảo rằng bạn xem lại tập lệnh trước khi thực thi.

Công cụ của bên thứ ba

  • Ưu điểm: các công cụ như ApexSQL Diff (đây là những gì tôi sử dụng nhưng có nhiều công cụ khác như các công cụ từ Red Gate hoặc Dev Art) sẽ so sánh hai cơ sở dữ liệu trong một cú nhấp chuột và tạo tập lệnh mà bạn có thể thực thi ngay lập tức
  • Nhược điểm: những thứ này không miễn phí (mặc dù hầu hết các nhà cung cấp đều có bản dùng thử đầy đủ chức năng)

Chế độ xem hệ thống

  • Ưu điểm: Bạn có thể dễ dàng xem các thủ tục được lưu trữ nào tồn tại trên máy chủ phụ và chỉ tạo ra những thủ tục bạn không có.
  • Nhược điểm: Yêu cầu kiến ​​thức SQL nhiều hơn một chút

Đây là cách lấy danh sách tất cả các thủ tục trong một số cơ sở dữ liệu không tồn tại trong cơ sở dữ liệu khác

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

5

Ban đầu tôi thấy bài đăng này đang tìm kiếm giải pháp để sao chép các quy trình được lưu trữ từ cơ sở dữ liệu sản xuất từ ​​xa sang cơ sở dữ liệu phát triển cục bộ của tôi. Sau khi thành công khi sử dụng cách tiếp cận được đề xuất trong chuỗi này, tôi nhận ra rằng mình ngày càng lười biếng (hoặc tháo vát, tùy bạn thích) và muốn điều này được tự động hóa. Tôi đã xem qua liên kết này , được chứng minh là rất hữu ích (cảm ơn bạn vincpa), và tôi đã mở rộng nó, dẫn đến tệp sau (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()

Tôi có một tệp .bat gọi điều này và được gọi từ Trình lập lịch tác vụ. Sau cuộc gọi đến tệp Powershell, tôi có:

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

Dòng đó sẽ đi qua thư mục và thả các thủ tục mà nó sẽ tạo lại. Nếu đây không phải là một môi trường phát triển, tôi sẽ không muốn bỏ qua các thủ tục theo cách lập trình theo cách này. Sau đó, tôi đổi tên tất cả các tệp thủ tục được lưu trữ thành .sql:

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

Và sau đó chạy:

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

Và điều đó lặp lại qua tất cả các tệp .sql và tạo lại các thủ tục được lưu trữ. Tôi hy vọng rằng bất kỳ phần nào trong số này sẽ hữu ích cho ai đó.


Tôi thích điều này. Tôi phải viết một quy trình để lưu trữ các phần từ DB sản xuất mỗi năm một lần. Tôi không muốn có các tệp SQL bị treo mà có thể sẽ không được cập nhật khi lược đồ phát triển, vì vậy tôi đang điều chỉnh điều này để tạo một DB trống dựa trên một mục tiêu mà không cần bước trung gian là ghi tệp vào đĩa (thêm để dọn dẹp). Tôi nghĩ đây có lẽ là câu trả lời tốt nhất và có thể tái sử dụng nhiều nhất cho câu hỏi này, thưa ông kudos!
Steve Pettifer

3

Bạn có thể sử dụng chức năng "Tạo tập lệnh ..." của SSMS để tạo tập lệnh cho bất kỳ thứ gì bạn cần chuyển. Nhấp chuột phải vào cơ sở dữ liệu nguồn trong SSMS, chọn "Tạo Tập lệnh ..." và làm theo trình hướng dẫn. Sau đó, chạy tập lệnh kết quả của bạn bây giờ sẽ chứa các câu lệnh tạo thủ tục được lưu trữ.


3

sử dụng

select * from sys.procedures

để hiển thị tất cả các thủ tục của bạn;

sp_helptext @objname = 'Procedure_name'

để lấy mã

và sự sáng tạo của bạn để xây dựng một cái gì đó lặp lại tất cả chúng và tạo mã xuất :)


3

Bạn có thể tạo script của proc được lưu trữ như được mô tả trong các câu trả lời khác. Khi tập lệnh đã được tạo, bạn có thể sử dụng sqlcmdđể thực thi chúng đối với DB đích như

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

0

Trong Mgmt Studio, nhấp chuột phải vào cơ sở dữ liệu ban đầu của bạn, sau đó nhấp vào Nhiệm vụ rồi Tạo tập lệnh ... - hãy làm theo trình hướng dẫn.


0

CHỌN định nghĩa + char (13) + 'ĐI' TỪ MyDatabase.sys.sql_modules s BÊN TRONG THAM GIA MyDatabase.sys.procedures p ON [s]. [Object_id] = [p]. [Object_id] WHERE p.name LIKE 'Something% '"queryout" c: \ SP_scripts.sql -S MyInstance -T -t -w

lấy sp và thực hiện nó


Đây là một giải pháp rất hay, nhưng 1) bạn nên chỉ ra rằng văn bản hoặc đầu ra tệp là cần thiết (không hiển thị kết quả trong lưới, nếu không bạn sẽ mất ký tự EOL) và 2) dường như có giới hạn 8k cho đầu ra văn bản trong studio Quản lý máy chủ SQL.
DAB

0

Một tùy chọn khác là chuyển các thủ tục được lưu trữ bằng cách sử dụng Dịch vụ Tích hợp Máy chủ SQL (SSIS) . Có một nhiệm vụ được gọi là Chuyển Nhiệm vụ Đối tượng Máy chủ SQL . Bạn có thể sử dụng tác vụ để chuyển các mục sau:

  • Những cái bàn
  • Lượt xem
  • Thủ tục lưu trữ
  • Chức năng do người dùng xác định
  • Mặc định
  • Loại dữ liệu do người dùng xác định
  • Chức năng phân vùng
  • Lược đồ phân vùng
  • Lược đồ
  • Lắp ráp
  • Tổng hợp do người dùng xác định
  • Loại do người dùng xác định
  • Bộ sưu tập lược đồ XML

Đó là một hướng dẫn đồ họa cho Nhiệm vụ Chuyển đối tượng Máy chủ SQL.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.