SQL Server - 将存储过程从一个数据库复制到另一个数据库
Posted
技术标签:
【中文标题】SQL Server - 将存储过程从一个数据库复制到另一个数据库【英文标题】:SQL Server - copy stored procedures from one db to another 【发布时间】:2012-05-29 00:37:50 【问题描述】:我是 SQL 新手,我需要做的是将 2 个 .mdf 数据库合并为一个。我使用 SQL Server 2008 管理器 - 任务 > 导入/导出表来做到这一点。表和视图已成功复制,但新数据库中没有存储过程。有什么办法吗?
【问题讨论】:
如果您想以编程方式复制它们,请从这里开始:***.com/a/6124487/138938 【参考方案1】: 右键数据库 任务 生成脚本 选择要编写脚本的对象 脚本文件 针对目标数据库运行生成的脚本【讨论】:
您好,感谢您的快速回复。您能否解释一下如何对目标数据库使用脚本。我是新手。 @BarryKaye 如果他有 30-40 个存储过程怎么办?右键会不会有点慢? @Oak 在 SQL Management Studio 中打开生成脚本文件。将连接更改为新数据库。将文件顶部“使用数据库名称”的行更改为您的数据库并执行。 哇。现在我认为我是唯一一个喜欢基于 GUI 的方法的人! @RajivVarma - 您为数据库执行一次此任务 - 而不是每个 SP!如果您勾选“存储过程”旁边的***复选框,它会一起选择它们 - 1次点击。【参考方案2】:此代码将Master数据库中的所有存储过程复制到目标数据库,您可以通过过滤过程名称的查询来仅复制您喜欢的过程。
@sql 定义为 nvarchar(max),@Name 是目标数据库
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
【讨论】:
谢谢!...在 cmets 中,但未在代码中声明的是@sql
& @Name
: DECLARE @sql NVARCHAR(MAX); DECLARE @Name NVARCHAR(32);
有没有办法在不同的服务器上做同样的事情?从服务器 A 到服务器 B?【参考方案3】:
晚了,但提供了更多可能有用的细节……
这里列出了你可以做的事情的优点和缺点
使用 SSMS 生成脚本
优点:非常易于使用且默认支持 缺点: 脚本的执行顺序可能不正确,如果辅助数据库上已存在存储过程,您可能会遇到错误。确保在执行之前查看脚本。第三方工具
优点: 诸如 ApexSQL Diff 之类的工具(这是我使用的,但还有许多其他工具,例如 Red Gate 或 Dev Art 的工具)将一键比较两个数据库并生成可以立即执行的脚本 缺点:这些不是免费的(不过大多数供应商都有功能齐全的试用版)系统视图
优点:您可以轻松查看辅助服务器上存在哪些存储过程,并且只生成那些您没有的存储过程。 缺点:需要更多的 SQL 知识这里是如何获取某个数据库中不存在于另一个数据库中的所有过程的列表
select *
from DB1.sys.procedures P
where P.name not in
(select name from DB2.sys.procedures P2)
【讨论】:
【参考方案4】:我最初发现这篇文章是为了寻找将存储过程从远程生产数据库复制到本地开发数据库的解决方案。在成功使用此线程中建议的方法后,我意识到我变得越来越懒惰(或足智多谋,无论你喜欢哪个),并希望它能够自动化。我遇到了this link,它被证明非常有帮助(感谢vincpa),我对其进行了扩展,得到了以下文件(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()
我有一个调用它的 .bat 文件,并从任务计划程序调用。调用 Powershell 文件后,我有:
for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /Q "DROP PROCEDURE %f"
该行将通过目录并删除将要重新创建的过程。如果这不是一个开发环境,我不希望以这种方式以编程方式删除程序。然后我将所有存储过程文件重命名为 .sql:
powershell Dir d:\prod_schema_backup\stp\ | Rename-Item -NewName $_.name + ".sql"
然后运行:
for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /E /i "%f".sql
这会遍历所有 .sql 文件并重新创建存储过程。我希望其中的任何部分都对某人有所帮助。
【讨论】:
我喜欢这个。我必须编写一个流程,以一次从生产数据库中归档数据块。我不想让 SQL 文件挂在上面,这些文件可能不会随着架构的发展而更新,所以我正在调整它以基于目标创建一个空数据库,而无需将文件写入磁盘的中间步骤(更多清理)。我认为这可能是这个问题上最好和最可重复使用的答案,先生!【参考方案5】:使用
select * from sys.procedures
显示您的所有程序;
sp_helptext @objname = 'Procedure_name'
获取代码
还有你的创造力来构建一些东西来循环它们并生成导出代码:)
【讨论】:
【参考方案6】:您可以使用 SSMS 的“生成脚本...”功能来编写您需要传输的任何内容。右键单击 SSMS 中的源数据库,选择“生成脚本...”,然后按照向导进行操作。然后运行生成的脚本,该脚本现在将包含存储过程创建语句。
【讨论】:
【参考方案7】:您可以生成存储过程的脚本,如其他答案中所述。生成脚本后,您可以使用sqlcmd
对目标数据库执行它们,例如
sqlcmd -S <server name> -U <user name> -d <DB name> -i <script file> -o <output log file>
【讨论】:
【参考方案8】:另一种选择是使用 SQL Server Integration Services (SSIS) 传输存储过程。有一个名为Transfer SQL Server Objects Task 的任务。您可以使用该任务转移以下物品:
表格 观看次数 存储过程 用户定义函数 默认值 用户定义的数据类型 分区函数 分区方案 架构 程序集 用户定义的聚合 用户定义的类型 XML 模式集合这是一个graphical tutorial,用于传输 SQL Server 对象任务。
【讨论】:
【参考方案9】:在 Mgmt Studio 中,右键单击您的原始数据库,然后右键单击任务,然后生成脚本... - 按照向导进行操作。
【讨论】:
【参考方案10】:SELECT 定义 + char(13) + 'GO' FROM MyDatabase.sys.sql_modules s INNER JOIN 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
获取 sp 并执行它
【讨论】:
这是一个非常好的解决方案,但是 1)您应该指出需要文本或文件输出(不要在网格中显示结果,否则您将丢失 EOL 字符)和 2) SQL Server Management Studio 中的文本输出似乎有 8k 的限制。以上是关于SQL Server - 将存储过程从一个数据库复制到另一个数据库的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server - 将存储过程从一个数据库复制到另一个数据库
将数据从 MS Sql Server 存储过程导出到 excel 文件
将 SQL Server 存储过程转换为 Oracle 过程以从表中查询