我想将我的MS SQL Server 2005存储过程自动保存到.sql文件中(更喜欢我可以通过.bat调用的工具)所以我不必手动点击每个sproc并保存它。
我已经从devio IT中找到了SMOscript,但它收集了所有需要一些时间的表和sproc。有没有类似的工具,我可以定义哪些sproc(s)导出?此外,我错过了USE子句,其中SMOScript不会添加到导出文件,而不是作为CREATE脚本sproc的manuall导出。
最好的问候 肖恩答案 0 :(得分:5)
使用脚本创建批处理文件(抱歉格式化,但实际上应该内联执行批处理):
osql -U %1 -P %2 -S %3 -d %4 -h-1 -Q "SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.Routines WHERE ROUTINE_TYPE = 'PROCEDURE'" -n -o "sp_list.txt"
for /f %%a in (sp_list.txt) do osql -U %1 -P %2 -S %3 -d %4 -h-1 -Q "SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.Routines WHERE ROUTINE_NAME = '%%a'" -n -o "%%a.sql"
将其命名为“run.bat”。现在,执行批处理使用参数:
run.bat [用户名] [密码] [服务器名] [数据库]
例如:
run.bat sa pwd111 localhost \ SQLEXPRESS master
首先,所有存储过程名称将存储在文件sp_list.txt中,然后逐个存储在单独的脚本文件中。唯一的问题 - 每个脚本的最后一行都有结果计数 - 我正在研究它:)
已编辑:已修复查询中的错误
删除“受影响的行”行
好的,现在我们需要再创建一个批次:
type %1 | findstr /V /i %2 > xxxtmpfile
copy xxxtmpfile %1 /y /v
del xxxtmpfile
将其命名为“line_del.bat”。看,第一个参数是要处理的文件,第二个 - 用于搜索要删除的行的字符串。现在修改主批次(再次,抱歉格式化):
osql -U %1 -P %2 -S %3 -d %4 -h-1 -Q "SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.Routines WHERE ROUTINE_TYPE = 'PROCEDURE'" -n -o "sp_list.txt"
call line_del sp_list.txt "rows affected"
call line_del sp_list.txt "row affected"
for /f %%a in (sp_list.txt) do osql -U %1 -P %2 -S %3 -d %4 -h-1 -Q "SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.Routines WHERE ROUTINE_NAME = '%%a'" -n -o "%%a.sql"
for /f %%a in (sp_list.txt) do call line_del %%a.sql "rows affected"
for /f %%a in (sp_list.txt) do call line_del %%a.sql "row affected"
见相关文章:
Simple programming commands in a batch environment
osql Utility
MSSQL: How do you script Stored Procedure creation with code?
Delete certain lines in a txt file via a batch file
:)你可能会注意到,最后两个来自SO!
答案 1 :(得分:2)
SQL Server Management Studio中有一种替代方法,可以编写数据库脚本......
展开Object Explorer视图以查找数据库,右键单击并选择“Tasks:Generate Scripts”
从那里你可以编写所有对象,只是存储的预处理,中间的任何东西。一个页面上有很多选项,但我更改的主要选项是: - “包括IF NOT EXISTS”
通过将该选项设为“FALSE”,您只需获得一份CREATE语句的完整列表。
然后,您可以选择将对象编写为新的查询窗口或文件。
答案 2 :(得分:1)
添加SET NOCOUNT ON确实消除了对line_del.bat的需要,但是用sys.sql_modules替换syscomments会导致每个存储过程被截断为258个字符。因此,为了获得最佳结果,我使用的代码是:
sqlcmd -E -S SERVER-d DB -h-1 -Q "SET NOCOUNT ON SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.Routines WHERE ROUTINE_TYPE = 'PROCEDURE'" -o "sp_list.txt"
for /f %%a in (sp_list.txt) do sqlcmd -E -S SERVER-d DB -h-1 -Q "SET NOCOUNT ON SELECT text from dbo.syscomments WHERE id = OBJECT_ID('%%a')" -o "%%a.sql"
哪个有效,并且不需要使用line_del.bat。当我使用SSMS向导(任务/生成脚本/存储过程/全选)进行手动导出时,我没有得到的是:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
在每个.sql的开头,以及尾随GO命令。不是很重要但需要注意的事项。感谢Max Gontar,Seansilver和Lee的贡献!我现在可以自动备份数据库中的存储过程,并应用版本控制。
答案 3 :(得分:0)
我想在不久前做同样的事情,我最后通过制作一个小的vbscript来做到这一点。
答案 4 :(得分:0)
我使用了sqlcmd和-E而不是user,传递。到目前为止,此工作正常,只有超过4000个字符的存储过程将有一个换行符
sqlcmd -E -S SERVER -d DB -h-1 -Q "SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.Routines WHERE ROUTINE_TYPE = 'PROCEDURE'" -o "sp_list.txt"
call line_del sp_list.txt "rows affected"
call line_del sp_list.txt "row affected"
for /f %%a in (sp_list.txt) do sqlcmd -E -S SERVER -d DB -h-1 -Q "SELECT text from dbo.syscomments WHERE id = OBJECT_ID('%%a')" -o "%%a.sql"
for /f %%a in (sp_list.txt) do call line_del %%a.sql "rows affected"
for /f %%a in (sp_list.txt) do call line_del %%a.sql "row affected"
最好的问候
肖恩
答案 5 :(得分:0)
我添加了SET NOCOUNT ON以消除对line_del.bat的需求。还用sys.sql_modules替换了syscomments(SQL 2005)。我也可以使用OBJECT_DEFINITION函数,但它比sys.sql_modules慢。
sqlcmd -E -S SERVER -d DB -h-1 -Q "SET NOCOUNT ON SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.Routines WHERE ROUTINE_TYPE = 'PROCEDURE'" -o "sp_list.txt" for /f %%a in (sp_list.txt) do sqlcmd -E -S SERVER -d DB -h-1 -Q "SET NOCOUNT ON SELECT definition from sys.sql_modules WHERE object_id = OBJECT_ID('%%a')" -o "%%a.sql"
答案 6 :(得分:0)
感谢以上所有人的帮助,并将此留给其他像我这样的sqlcmd noobs找到。适用于sql server 2005. objectName是一个过程,视图等名称。
:reset
-- :setvar ObjectName "objectName" -- works
:setvar ObjectName objectName -- works too
declare @sql varchar(max);
set @sql = 'select text from dbo.syscomments where id = object_id(upper("' + '$(ObjectName)' + '"))';
-- exec sp_helptext $(ObjectName) -- quick n easy but gets chopped to 256 width
/* 4000 byte limit
set @sql =
'select view_definition
from information_schema.views
where upper(table_name) = upper("' + '$(ObjectName)' + '")';
*/
:out $(ObjectName).sql
exec(@sql)
go
:out stdout