67

关于如何以编程方式从 SQL Server 2005 中获取完全相同的存储过程源的任何指针,就像我在 SQL Server Management Studio 中右键单击该存储过程并选择修改时一样?

我正在尝试使用 SMO,但存在一些文本差异。该过程始终具有 CREATE,而不是 ALTER,并且标头中存在一些差异,例如我以编程方式获得的版本中缺少 GO。我可以解决这些问题,但也许有更好的方法?

同样,我在 SQL Server 2005 中,使用 SMSE。通过 Visual Studio 8 2008 使用 SMO。

更新:得到了一些答案,告诉了如何检索存储过程的基础知识。我正在寻找的是检索与 GUI 生成的文本相同(或几乎相同)的文本。

示例:对于 sp_mysp,在 Management Studio 中单击鼠标右键,选择修改。这会产生:

    使用 [MY_DB]  
    去  
    /****** 对象:StoredProcedure [dbo].[sp_mysp] 脚本日期:01/21/2009 17:43:18 ******/  
    设置 ANSI_NULLS ON  
    去  
    设置 QUOTED_IDENTIFIER ON  
    去  
    -- ===============================================
    -  作者:      
    -- 创建日期:
    -  描述:
    -- ===============================================
    更改程序 [dbo].[sp_mysp]

我想以编程方式获得相同的东西(注意标题中的 GO,以及它是一个 ALTER PROCEDURE 的事实。理想情况下,我希望通过对检索到的源进行最少的编程修复来获得它。

我很乐意只得到与 Script Date details 不同的东西。. .

4

9 回答 9

83
EXEC sp_helptext 'your procedure name';

这避免了 INFORMATION_SCHEMA 方法的问题,即存储过程如果太长就会被切断。

更新:大卫写道,这与他的存储过程不同......也许是因为它将行作为“记录”返回以保留格式?如果您想以更“自然”的格式查看结果,您可以先使用 Ctrl-T(输出为文本),它应该完全按照您输入的格式打印出来。如果您在代码中执行此操作,那么执行 foreach 以完全相同的方式将您的结果放在一起是微不足道的。

更新 2:这将为源提供“CREATE PROCEDURE”而不是“ALTER PROCEDURE”,但我不知道没有办法让它使用“ALTER”。不过,这是一件微不足道的事情,不是吗?

更新 3:有关如何在源代码控制系统中维护 SQL DDL(数据库结构)的更多信息,请参阅评论。这确实是这个问题的关键。

于 2009-01-21T23:33:25.037 回答
16

您将不得不手动编写代码,SQL Profiler 显示以下内容。

SMSE 在生成语句时会执行相当长的查询字符串。

以下查询(或类似的内容)用于提取文本:

SELECT
NULL AS [Text],
ISNULL(smsp.definition, ssmsp.definition) AS [Definition]
FROM
sys.all_objects AS sp
LEFT OUTER JOIN sys.sql_modules AS smsp ON smsp.object_id = sp.object_id
LEFT OUTER JOIN sys.system_sql_modules AS ssmsp ON ssmsp.object_id = sp.object_id
WHERE
(sp.type = N'P' OR sp.type = N'RF' OR sp.type='PC')and(sp.name=N'#test___________________________________________________________________________________________________________________00003EE1' and SCHEMA_NAME(sp.schema_id)=N'dbo')

它返回纯 CREATE,然后在某处的代码中用 ALTER 替换。

SET ANSI NULL 内容和 GO 语句和日期都在此前面。

使用 sp_helptext,它更简单......

于 2009-01-22T00:04:53.413 回答
12

你说的是程序化的,对吧?我希望 C# 没问题。我知道您说过您尝试了 SMO,但它并没有完全满足您的要求,因此这可能不适合您的请求,但它会以编程方式读出合法的 SQL 语句,您可以运行这些语句来重新创建存储过程。如果它没有GO你想要的语句,你可以假设每个字符串后面StringCollection都有一个GO。您可能没有得到包含日期和时间的评论,但在我类似的听起来项目(必须单独备份所有内容的大屁股部署工具)中,这做得相当好。如果您有一个想要工作的先前基础,并且您仍然有原始数据库来运行它,我会考虑放弃最初的努力并重新标准化这个输出。

using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
…
string connectionString = … /* some connection string */;
ServerConnection sc = new ServerConnection(connectionString);
Server s = new Server(connection);
Database db = new Database(s, … /* database name */);
StoredProcedure sp = new StoredProcedure(db, … /* stored procedure name */);
StringCollection statements = sp.Script;
于 2009-06-02T04:56:19.610 回答
9

使用以下 select 语句获取整个定义:

select ROUTINE_DEFINITION 
  from INFORMATION_SCHEMA.ROUTINES 
 where ROUTINE_NAME = 'someprocname'

我猜 SSMS 和其他工具会读出来并在必要时进行更改,例如将 CREATE 更改为 ALTER。据我所知,SQL 不存储过程的其他表示形式。

于 2009-01-21T23:27:48.620 回答
5

我同意马克。我将输出设置为文本模式,然后设置 sp_HelpText 'sproc'。我将此绑定到 Crtl-F1 以使其变得容易。

于 2009-01-21T23:43:21.103 回答
4

数据库发布向导可以从命令行转储架构(和其他对象)。

于 2009-01-22T05:34:05.090 回答
2

我只想注意,不要使用查找和替换来更改创建过程以更改过程,您也可以使用 drop,您可以将其放在顶部,并且确实需要文本搜索。

IF exists (SELECT * FROM sys.objects 
        WHERE object_id = OBJECT_ID(N'sp_name')
            and type in ('P','V') --procedure or view
        )
    DROP sp_name
GO

如果你确定它在那里,我想你也可以放弃它,但我不建议这样做。不要忘记 go,因为 create procedure 必须是批处理中的第一个也是唯一的语句。

或懒惰的方法:

IF OBJECT_ID(N'sp_name') is not null
    DROP sp_name
GO
于 2012-02-03T13:34:24.037 回答
0

我通过链接看到了一篇文章。有四种方法,我这里只是做了一个简短的总结,以帮助其他程序员。

  1. 执行 sp_helptext 'sp_name';

  2. SELECT OBJECT_ID('sp_name')

  3. 选择 OBJECT_DEFINITION( OBJECT_ID('sp_name') ) 作为 [定义];

  4. SELECT * FROM sys.sql_modules WHERE object_id = object_id('sp_name');

于 2020-07-06T09:32:44.853 回答
-2

要更改存储过程,下面是 C# 代码:

SqlConnection con = new SqlConnection("your connection string");
con.Open();
cmd.CommandType = System.Data.CommandType.Text;
string sql = File.ReadAllText(YUOR_SP_SCRIPT_FILENAME);
cmd.CommandText = sql;   
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();

注意事项:

  1. 确保连接字符串中的 USER 有权更改 SP
  2. 从脚本文件中删除所有GO,SET ANSI_NULLS XX,SET QUOTED_IDENTIFIER语句。(如果不这样做,SqlCommand 将抛出错误)。
于 2010-03-18T09:36:29.703 回答