以编程方式获取所有存储过程的简单方法

12
有没有办法使用C#从SQL Server 2005 Express数据库中获取存储过程?我想以与使用SQL Server Management Studio脚本的方式相同的方式导出所有这些数据,而不必安装GUI界面。 我看到了一些关于通过PowerShell实现此操作的参考资料,但最终我真正想要的是一个C#控制台应用程序。 澄清一下.... 我想编写存储过程的脚本。通过Select * from sys.procedures命令的列表很有帮助,但最终我需要为每个存储过程编写脚本。
12个回答

22

你可以使用SMO来完成这个任务。首先,将这些程序集的引用添加到您的项目中:

  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Smo
  • Microsoft.SqlServer.SmoEnum

它们位于GAC中(浏览到C:\WINDOWS\assembly文件夹)。

使用以下代码作为脚本存储过程的示例:

using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.SqlServer.Management.Smo;

class Program
{
   static void Main(string[] args)
   {
      Server server = new Server(@".\SQLEXPRESS");
      Database db = server.Databases["Northwind"];
      List<SqlSmoObject> list = new List<SqlSmoObject>();
      DataTable dataTable = db.EnumObjects(DatabaseObjectTypes.StoredProcedure);
      foreach (DataRow row in dataTable.Rows)
      {
         string sSchema = (string)row["Schema"];
         if (sSchema == "sys" || sSchema == "INFORMATION_SCHEMA")
            continue;
         StoredProcedure sp = (StoredProcedure)server.GetSmoObject(
            new Urn((string)row["Urn"]));
         if (!sp.IsSystemObject)
            list.Add(sp);
      }
      Scripter scripter = new Scripter();
      scripter.Server = server;
      scripter.Options.IncludeHeaders = true;
      scripter.Options.SchemaQualify = true;
      scripter.Options.ToFileOnly = true;
      scripter.Options.FileName = @"C:\StoredProcedures.sql";
      scripter.Script(list.ToArray());
   }
}

参见:SQL Server:SMO脚本基础知识


您可能还需要在C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies中查找所需的参考资料。 - user423430
1
我还需要引用 Microsoft.SqlServer.Management.Sdk.Sfc。 - user423430
1
从Sql Server 2008R2开始,URN类已经移动到程序集Microsoft.SqlServer.Management.Sdk.Sfc的命名空间Microsoft.SqlServer.Management.Sdk.Sfc中。 - Alexander Garden

6

只需读取 SYS.PROCEDURES 中 SELECT NAME 的输出,然后为每个存储过程调用 EXEC sp_HelpText SPNAME,您将获得每行一个文本的记录集。


1
从 SYS.PROCEDURES 中选择 NAME 会返回系统存储过程,而不是用户定义的存储过程。如果您在 SSMS 中运行此语句,则会获取所有存储过程。通过 C# 代码运行此语句将仅返回系统存储过程,正如我所说的那样。 - Sam Saarian

3
;WITH ROUTINES AS (
    -- CANNOT use INFORMATION_SCHEMA.ROUTINES because of 4000 character limit
    SELECT o.type_desc AS ROUTINE_TYPE
            ,o.[name] AS ROUTINE_NAME
            ,m.definition AS ROUTINE_DEFINITION
    FROM sys.sql_modules AS m
    INNER JOIN sys.objects AS o
        ON m.object_id = o.object_id
)
SELECT *
FROM ROUTINES

3
public static void GenerateTableScript()
    {
        Server databaseServer = default(Server);//DataBase Server Name
        databaseServer = new Server("yourDatabase Server Name");
        string strFileName = @"C:\Images\Your FileName_" + DateTime.Today.ToString("yyyyMMdd") + ".sql"; //20120720`enter code here
        if (System.IO.File.Exists(strFileName))
            System.IO.File.Delete(strFileName);
        List<SqlSmoObject> list = new List<SqlSmoObject>();
        Scripter scripter = new Scripter(databaseServer);
        Database dbUltimateSurvey = databaseServer.Databases["YourDataBaseName"];//DataBase Name
        //Table scripting Writing
        DataTable dataTable1 = dbUltimateSurvey.EnumObjects(DatabaseObjectTypes.Table);
        foreach (DataRow drTable in dataTable1.Rows)
        {
            //string strTableSchema = (string)drTable["Schema"];
            //if (strTableSchema == "dbo")
            //    continue;
            Table dbTable = (Table)databaseServer.GetSmoObject(new Urn((string)drTable["Urn"]));
            if (!dbTable.IsSystemObject)
                if (dbTable.Name.Contains("SASTool_"))
                    list.Add(dbTable);
        }
        scripter.Server = databaseServer;
        scripter.Options.IncludeHeaders = true;
        scripter.Options.SchemaQualify = true;
        scripter.Options.ToFileOnly = true;
        scripter.Options.FileName = strFileName;
        scripter.Options.DriAll = true;
        scripter.Options.AppendToFile = true;
        scripter.Script(list.ToArray());//Table Script completed
        //Store Procedures scripting Writing
        list = new List<SqlSmoObject>();
        DataTable dataTable = dbUltimateSurvey.EnumObjects(DatabaseObjectTypes.StoredProcedure);
        foreach (DataRow row in dataTable.Rows)
        {
            string sSchema = (string)row["Schema"];
            if (sSchema == "sys" || sSchema == "INFORMATION_SCHEMA")
                continue;
            StoredProcedure sp = (StoredProcedure)databaseServer.GetSmoObject(
               new Urn((string)row["Urn"]));
            if (!sp.IsSystemObject)
                if (sp.Name.Contains("custom_"))
                    list.Add(sp);
        }
        scripter.Server = databaseServer;
        scripter.Options.IncludeHeaders = true;
        scripter.Options.SchemaQualify = true;
        scripter.Options.ToFileOnly = true;
        scripter.Options.FileName = strFileName;
        scripter.Options.DriAll = true;
        scripter.Options.AppendToFile = true;
        scripter.Script(list.ToArray());   // Stored procedure Script completed
    }

2
这篇博客建议在你的数据库中运行以下代码来列出所有存储过程:

This blog post

select * from sys.procedures

2

您可以使用:

DataTable  dtProcs = sqlConn.GetSchema("Procedures", new string[] { databaseName });
DataTable  dtProcParams = sqlConn.GetSchema("ProcedureParameters", new string[] { databaseName });

您还可以获取各种其他模式信息,例如表、索引等,如果您需要的话。
您可以在此处获取有关GetSchema()的信息,并在此处获取有关SQL Server模式集合的信息。
编辑:对不起,这不能帮助您实际编写脚本的信息,但我想这是有用的信息。

0

这是我刚在MSSQL中测试和使用的SQL语句

SELECT NAME from SYS.PROCEDURES 
order by name

如果你需要查找特定的名称或子字符串/文本

SELECT NAME from SYS.PROCEDURES 
where name like '%<TEXT_TO_LOOK_FOR>%'
order by name

将“<br>”替换为完全相同的内容,例如:

SELECT NAME from SYS.PROCEDURES 
where name like '%CUSTOMER%'
order by name

而且调用

EXEC sp_HelpText SPNAME 

对于每个存储过程,您将获得一个记录集,每行文本为一行


0
如果你在 sqlmetal.exe 上打开反射器(LINQ-to-SQL 的一个独立部分,用于从数据库生成代码),你可以看到它使用的 SQL 语句来获取所有存储过程和函数的列表。这个 SQL 与 此答案中的 SQL 类似,但并不完全相同。

0
begin
--select column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Products' 
--Declare the Table variable 
DECLARE @GeneratedStoredProcedures TABLE
(
        Number INT IDENTITY(1,1), --Auto incrementing Identity column
        name VARCHAR(300) --The string value
)

--Decalre a variable to remember the position of the current delimiter
DECLARE @CurrentDelimiterPositionVar INT 
declare @sqlCode varchar(max)
--Decalre a variable to remember the number of rows in the table
DECLARE @Count INT

--Populate the TABLE variable using some logic
INSERT INTO @GeneratedStoredProcedures SELECT name FROM sys.procedures where name like 'procGen_%'

--Initialize the looper variable
SET @CurrentDelimiterPositionVar = 1

--Determine the number of rows in the Table
SELECT @Count=max(Number) from @GeneratedStoredProcedures

--A variable to hold the currently selected value from the table
DECLARE @CurrentValue varchar(300);

--Loop through until all row processing is done
WHILE @CurrentDelimiterPositionVar <= @Count
BEGIN
    --Load current value from the Table
    SELECT @CurrentValue = name FROM @GeneratedStoredProcedures WHERE Number = @CurrentDelimiterPositionVar 
    --Process the current value
    --print @CurrentValue
    set @sqlCode = 'drop procedure ' + @CurrentValue
    print @sqlCode
    --exec (@sqlCode)


    --Increment loop counter
    SET @CurrentDelimiterPositionVar = @CurrentDelimiterPositionVar + 1;
END

end

0
您可以编写 C# 代码在数据库上运行以下查询。
Select * from sys.procedures

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接