通过SQL脚本导出存储过程
Was:如何使用查询备份所选存储过程 我想通过命令行(在SQLServerManagementStudio中)备份200个存储过程中的10个。有没有简单的方法 现在,我正在使用数据库->任务->生成脚本选项,这将引导我通过一系列对话框选择要导出的SP。我想让这个过程变得简单,这样我就不必从头再来了通过SQL脚本导出存储过程,sql,sql-server-2005,stored-procedures,backup,ssms,Sql,Sql Server 2005,Stored Procedures,Backup,Ssms,Was:如何使用查询备份所选存储过程 我想通过命令行(在SQLServerManagementStudio中)备份200个存储过程中的10个。有没有简单的方法 现在,我正在使用数据库->任务->生成脚本选项,这将引导我通过一系列对话框选择要导出的SP。我想让这个过程变得简单,这样我就不必从头再来了 注意:导出是指在屏幕上打印,以便复制并保存在文本文件中。您可以通过以下查询选择所需的SP: SELECT obj.Name as SPName, modu.definition as SPDefin
注意:导出是指在屏幕上打印,以便复制并保存在文本文件中。您可以通过以下查询选择所需的SP:
SELECT obj.Name as SPName,
modu.definition as SPDefinition,
obj.create_date as SPCreationDate
FROM sys.sql_modules modu
INNER JOIN sys.objects obj
ON modu.object_id = obj.object_id
WHERE obj.type = 'P' AND obj.Name IN ('sp1','sp2', ect)
另见:和
看看这个。这可能对你有帮助
declare @S nvarchar(max)
set @S = N''
select @S = @S + [definition] +
nchar(13) + nchar(10) +
N'GO' +
nchar(13) + nchar(10)
from sys.sql_modules as m
inner join sys.objects as o
on m.object_id = o.object_id
where o.create_date > '20120101' and
o.name in ('Proc1', 'Proc2', 'ProcN')
select @S
for xml path('')
单击结果窗格中的链接以查看整个脚本。下面的SQL应该执行您想要的操作
SET NOCOUNT ON
DECLARE @procs AS TABLE( object_id INT
, definition NVARCHAR(MAX)
, uses_ansi_nulls BIT
, uses_quoted_identifier BIT
)
INSERT INTO @procs
SELECT m.object_id
, m.definition
, m.uses_ansi_nulls
, m.uses_quoted_identifier
FROM sys.sql_modules AS m
INNER JOIN sys.objects AS o
ON m.object_id = o.object_id
WHERE o.type = 'P'
--Change this part to suit your needs...
AND o.name IN ('sproc1'
,'sproc2'
,'sproc3'
)
--Optionally filter by date?
--AND o.create_date >= '02/01/2012'
DECLARE @endStmt NCHAR(6)
, @object_id INT
, @definition NVARCHAR(MAX)
, @uses_ansi_nulls BIT
, @uses_quoted_identifier BIT
SELECT @object_id = MIN(object_id)
, @endStmt = CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10)
FROM @procs
WHILE ISNULL(@object_id,0) > 0
BEGIN
SELECT @definition = definition
, @uses_ansi_nulls = uses_ansi_nulls
, @uses_quoted_identifier = uses_quoted_identifier
FROM @procs
IF @uses_ansi_nulls = 1
PRINT 'SET ANSI_NULLS ON' + @endStmt
ELSE
PRINT 'SET ANSI_NULLS OFF' + @endStmt
IF @uses_quoted_identifier = 1
PRINT 'SET QUOTED_IDENTIFIER ON' + @endStmt
ELSE
PRINT 'SET QUOTED_IDENTIFIER OFF' + @endStmt
IF LEN(@definition) <= 4000
PRINT @definition
ELSE
BEGIN
DECLARE @crlf VARCHAR(2), @len BIGINT, @offset BIGINT, @part BIGINT
SELECT @crlf = CHAR(13)+CHAR(10)
, @len = LEN(@definition)
, @offset = 1
, @part = CHARINDEX(@crlf,@definition)-1
WHILE @offset <= @len
BEGIN
PRINT SUBSTRING(@definition,@offset,@part)
SET @offset = @offset + @part + LEN(@crlf)
SET @part = CHARINDEX(@crlf,@definition,@offset)-@offset
END
END
PRINT @endStmt
SELECT @object_id = MIN(object_id)
FROM @procs
WHERE object_id > @object_id
END
如何使用信息_SCHEMA.Routines
DECLARE MY_CURSOR Cursor
FOR
SELECT r.Routine_Definition
FROM INFORMATION_SCHEMA.Routines r
OPEN MY_CURSOR
DECLARE @sproc VARCHAR(MAX)
FETCH NEXT FROM MY_CURSOR INTO @sproc
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
PRINT @sproc
FETCH NEXT FROM MY_CURSOR INTO @sproc
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
GO
不是SQL方式,但我认为您可以通过使用或其他GUI测试工具来自动化数据库->任务->生成脚本选项/…更多步骤 我尝试了一点Sikuli的网站,但它不是100%可靠的 AutoIt v3是一种类似于免费软件的基本脚本语言,专为 自动化Windows GUI和常规脚本
我编辑了MyItchyChin的脚本,因为我发现了其中的一些缺陷。当@part<0时,它将不精确地循环,并且不会正确打印关闭过程代码的“END”关键字(“create procedure…as begin…END”)。我也做了其他的小改动。我的问题现在解决了!非常感谢MyItchyChin的初始脚本 Obs:我在SQLServer2008R2中使用此脚本。该脚本还可用于编写函数脚本
SET NOCOUNT ON
DECLARE @procs AS TABLE( nome varchar(200),object_id INT
, definition NVARCHAR(MAX)
, uses_ansi_nulls BIT
, uses_quoted_identifier BIT
)
INSERT INTO @procs
SELECT o.name
,m.object_id
, m.definition
, m.uses_ansi_nulls
, m.uses_quoted_identifier
FROM sys.sql_modules AS m
INNER JOIN sys.objects AS o
ON m.object_id = o.object_id
WHERE 1=1
--and o.type = 'P'
AND o.name IN ('proc1')
DECLARE @endStmt NCHAR(6)
, @object_id INT
, @definition NVARCHAR(MAX)
, @uses_ansi_nulls BIT
, @uses_quoted_identifier BIT
DECLARE @crlf VARCHAR(2), @len BIGINT, @offset BIGINT, @part BIGINT
SELECT @object_id = MIN(object_id)
, @endStmt = CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10)
FROM @procs
declare c cursor for SELECT definition
, uses_ansi_nulls
, uses_quoted_identifier
FROM @procs
order by nome asc
open c
fetch next from c into @definition,@uses_ansi_nulls,@uses_quoted_identifier
while @@fetch_status<>-1
begin
IF @uses_ansi_nulls = 1
PRINT 'SET ANSI_NULLS ON' + @endStmt;
ELSE
PRINT 'SET ANSI_NULLS OFF' + @endStmt;
IF @uses_quoted_identifier = 1
PRINT 'SET QUOTED_IDENTIFIER ON' + @endStmt;
ELSE
PRINT 'SET QUOTED_IDENTIFIER OFF' + @endStmt;
--PRINT @definition;
IF LEN(@definition) <= 4000
PRINT @definition
ELSE
BEGIN
SELECT @crlf = CHAR(13)+CHAR(10)
, @len = LEN(@definition)
, @offset = 1
, @part = CHARINDEX(@crlf,@definition)-1
WHILE @offset <= @len AND @part>=0
BEGIN
--PRINT @offset
--PRINT @part
--PRINT LEN(@crlf)
--PRINT @len
PRINT SUBSTRING(@definition,@offset,@part)
SET @offset = @offset + @part + LEN(@crlf)
SET @part = CHARINDEX(@crlf,@definition,@offset)-@offset
--PRINT @offset
--PRINT @part
--PRINT @len
IF @part < 0
PRINT SUBSTRING(@definition,@offset,100)
END
END
PRINT @endStmt;
fetch next from c into @definition,@uses_ansi_nulls,@uses_quoted_identifier
end
close c
deallocate c
将NOCOUNT设置为ON
将@procs声明为表(nome varchar(200),object_id INT
,定义NVARCHAR(最大值)
,使用_ansi_nulls位
,使用带引号的标识符位
)
插入@procs
选择o.name
,m.object\u id
,m.定义
,m.uses_ansi_nulls
,m.使用带引号的标识符
来自sys.sql_模块,作为m
内部连接sys.objects作为o
在m.object\u id=o.object\u id上
其中1=1
--和o.type='P'
和('proc1'中的o.name)
声明@endStmt NCHAR(6)
,@object\u id INT
,@definition NVARCHAR(最大值)
,@使用\u ansi\u空位
,@使用带引号的标识符位
声明@crlf VARCHAR(2)、@len BIGINT、@offset BIGINT、@part BIGINT
选择@object\u id=MIN(object\u id)
,@endStmt=CHAR(13)+CHAR(10)+'GO'+CHAR(13)+CHAR(10)
来自@procs
为SELECT定义声明c游标
,使用_ansi_null
,使用带引号的标识符
来自@procs
诺姆asc订购
开c
从c获取下一个到@definition、@uses\u ansi\u nulls、@uses\u quoted\u标识符
当@@fetch\u状态为-1时
开始
如果@uses\u ansi\u nulls=1
在“+@endStmt”上打印“设置ANSI_空值”;
其他的
打印“设置ANSI_空值关闭”+@endStmt;
如果@uses\u quoted\u identifier=1
在“+@endStmt”上打印“SET QUOTED_标识符”;
其他的
打印“设置带引号的标识符关闭”+@endStmt;
--打印@定义;
如果LEN(@definition)我创建了以下过程,该过程将遍历特定数据库中的所有SP和视图(可以扩展到函数,…),并将每个代码脚本逐个存储到TXT文件中。在MS SQL 2008 R2和2014上测试
第一部分将SP和视图的所有脚本插入临时表。然后稍后使用BCP实用程序。如果您希望可以使用导出SSIS包,而不是像我在本例中所做的那样使用SP
DECLARE @File_name AS VARCHAR(255)
,@Folder_path AS VARCHAR(255)
,@File_Path_Name AS VARCHAR(255)
,@CMD AS VARCHAR(8000)
IF OBJECT_ID('tempdb..#TEMP_AA') IS NOT NULL DROP TABLE #TEMP_AA;
SELECT
T1.NAME AS ObjectName
,T1.type AS ObjectType
,STUFF(((SELECT ' ' + T.[TEXT]
FROM (SELECT SC.[id],SC.colid,SC.[TEXT]
FROM SYSCOMMENTS sc
) AS T
WHERE T.[id] = T1.[id]
ORDER BY T.colid
FOR XML PATH(''),TYPE
).value('.[1]', 'NVARCHAR(MAX)')
), 1, 1, '')
AS ObjectText
INTO #TEMP_AA
FROM SYSOBJECTS AS T1
WHERE 1=1
AND T1.type IN ('P', 'V') /* Procedures and Views*/
AND NOT T1.[name] LIKE 'dt_%'
循环通过临时表创建文件名,前缀为p_u或V_u,后缀为YYYYMMDD格式的日期:
-- Exporting Scripts one by one into TXT files
WHILE (SELECT TOP 1 objectName FROM #TEMP_AA) IS NOT NULL
BEGIN
SELECT TOP 1
@File_name = RTRIM(LTRIM(ObjectType)) + '_' + ObjectName +'_' + REPLACE(CAST(CAST(GETDATE()AS DATE) AS VARCHAR),'-','')
FROM #TEMP_AA;
IF OBJECT_ID('tempdb..##TEMP_BB') IS NOT NULL DROP TABLE ##TEMP_BB;
CREATE TABLE ##TEMP_BB (ObjectText VARCHAR(MAX));
INSERT INTO ##TEMP_BB
SELECT TOP 1 ObjectText
FROM #TEMP_AA;
--'Setting File name'
SET @Folder_Path = 'C:\AAAA\'
SET @File_Path_Name = @Folder_Path + @File_name + '.txt'
SET @CMD ='BCP ##TEMP_BB OUT "'+@File_Path_Name+'" -T -c -t "Your Server"'
-- 'Output via BCP into TXT file'
EXEC xp_cmdshell @CMD;
--Delete Line From temp which has been procese already
WITH CTE AS (SELECT TOP 1 * FROM #TEMP_AA)
DELETE FROM CTE;
END
我看到他们只列为10记录,我想它打印在SSMS的结构。如何将“modu.definition”的结果添加到临时表中。然后循环遍历临时表并打印每个结果。您只需要20条记录,就可以使用游标。我想选择此答案,但它会在一行中打印所有SP,有没有办法提高可读性?Ivo,您能否更改,以便在结果中包含新行字符?这似乎是唯一的问题。通过添加char(13)和char(10)可以得到一个新行,所以类似这样,modu.definition+char(13)+char(10)作为SPDefinitionBTW保存到文本文件并不重要,只需在SSMS中打印结果就足够了,我可以自己复制并保存。您能制作一个小型控制台应用程序来读取SP定义并将其写入文本文件吗?我不知道你将如何在tsql中完成这一切…使用游标和打印语句会变得很难看。我的意思是,这对我来说是可以接受的,我们将继续讨论。我在2012年1月之后更新的所有程序,我只想导出这些程序。这实际上解决了我的问题。当你说“命令行”时,你是指“cmd.exe”命令行还是SQL Server查询窗口?@Norla,不是cmd.exe。我指的是SQL Server管理查询。谢谢请看下面的部分查询。他们帮了我的忙,但不是全部。我能不能选择例程名称1、例程名称2等,因为这就是我想要的。@Thecrocodilehunter-我不知道你想要什么。是否要指定所需的过程而不是获取所有过程或…?我希望两个选项都有。但如果任何一个有效,那仍然是可以接受的。@Thecrocodilehunter Ok。我用where子句更新了答案,该子句过滤按名称导出的过程。我尝试了Update1查询,它没有打印整个子例程,只有两行。基本上与我刚才从answer1得到的结果相同。obj.create_date
应该是SO.created_date
,但它仍然没有给我想要的输出。超级。一个问题是,如果查询长度超过4000个字符,它会截断查询。有没有办法解决这个问题。如果您作为sepa执行单独的存储程序,我也可以
SET NOCOUNT ON
DECLARE @procs AS TABLE( nome varchar(200),object_id INT
, definition NVARCHAR(MAX)
, uses_ansi_nulls BIT
, uses_quoted_identifier BIT
)
INSERT INTO @procs
SELECT o.name
,m.object_id
, m.definition
, m.uses_ansi_nulls
, m.uses_quoted_identifier
FROM sys.sql_modules AS m
INNER JOIN sys.objects AS o
ON m.object_id = o.object_id
WHERE 1=1
--and o.type = 'P'
AND o.name IN ('proc1')
DECLARE @endStmt NCHAR(6)
, @object_id INT
, @definition NVARCHAR(MAX)
, @uses_ansi_nulls BIT
, @uses_quoted_identifier BIT
DECLARE @crlf VARCHAR(2), @len BIGINT, @offset BIGINT, @part BIGINT
SELECT @object_id = MIN(object_id)
, @endStmt = CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10)
FROM @procs
declare c cursor for SELECT definition
, uses_ansi_nulls
, uses_quoted_identifier
FROM @procs
order by nome asc
open c
fetch next from c into @definition,@uses_ansi_nulls,@uses_quoted_identifier
while @@fetch_status<>-1
begin
IF @uses_ansi_nulls = 1
PRINT 'SET ANSI_NULLS ON' + @endStmt;
ELSE
PRINT 'SET ANSI_NULLS OFF' + @endStmt;
IF @uses_quoted_identifier = 1
PRINT 'SET QUOTED_IDENTIFIER ON' + @endStmt;
ELSE
PRINT 'SET QUOTED_IDENTIFIER OFF' + @endStmt;
--PRINT @definition;
IF LEN(@definition) <= 4000
PRINT @definition
ELSE
BEGIN
SELECT @crlf = CHAR(13)+CHAR(10)
, @len = LEN(@definition)
, @offset = 1
, @part = CHARINDEX(@crlf,@definition)-1
WHILE @offset <= @len AND @part>=0
BEGIN
--PRINT @offset
--PRINT @part
--PRINT LEN(@crlf)
--PRINT @len
PRINT SUBSTRING(@definition,@offset,@part)
SET @offset = @offset + @part + LEN(@crlf)
SET @part = CHARINDEX(@crlf,@definition,@offset)-@offset
--PRINT @offset
--PRINT @part
--PRINT @len
IF @part < 0
PRINT SUBSTRING(@definition,@offset,100)
END
END
PRINT @endStmt;
fetch next from c into @definition,@uses_ansi_nulls,@uses_quoted_identifier
end
close c
deallocate c
DECLARE @File_name AS VARCHAR(255)
,@Folder_path AS VARCHAR(255)
,@File_Path_Name AS VARCHAR(255)
,@CMD AS VARCHAR(8000)
IF OBJECT_ID('tempdb..#TEMP_AA') IS NOT NULL DROP TABLE #TEMP_AA;
SELECT
T1.NAME AS ObjectName
,T1.type AS ObjectType
,STUFF(((SELECT ' ' + T.[TEXT]
FROM (SELECT SC.[id],SC.colid,SC.[TEXT]
FROM SYSCOMMENTS sc
) AS T
WHERE T.[id] = T1.[id]
ORDER BY T.colid
FOR XML PATH(''),TYPE
).value('.[1]', 'NVARCHAR(MAX)')
), 1, 1, '')
AS ObjectText
INTO #TEMP_AA
FROM SYSOBJECTS AS T1
WHERE 1=1
AND T1.type IN ('P', 'V') /* Procedures and Views*/
AND NOT T1.[name] LIKE 'dt_%'
-- Exporting Scripts one by one into TXT files
WHILE (SELECT TOP 1 objectName FROM #TEMP_AA) IS NOT NULL
BEGIN
SELECT TOP 1
@File_name = RTRIM(LTRIM(ObjectType)) + '_' + ObjectName +'_' + REPLACE(CAST(CAST(GETDATE()AS DATE) AS VARCHAR),'-','')
FROM #TEMP_AA;
IF OBJECT_ID('tempdb..##TEMP_BB') IS NOT NULL DROP TABLE ##TEMP_BB;
CREATE TABLE ##TEMP_BB (ObjectText VARCHAR(MAX));
INSERT INTO ##TEMP_BB
SELECT TOP 1 ObjectText
FROM #TEMP_AA;
--'Setting File name'
SET @Folder_Path = 'C:\AAAA\'
SET @File_Path_Name = @Folder_Path + @File_name + '.txt'
SET @CMD ='BCP ##TEMP_BB OUT "'+@File_Path_Name+'" -T -c -t "Your Server"'
-- 'Output via BCP into TXT file'
EXEC xp_cmdshell @CMD;
--Delete Line From temp which has been procese already
WITH CTE AS (SELECT TOP 1 * FROM #TEMP_AA)
DELETE FROM CTE;
END