【问题标题】:Number of Columns Each procedures returns T-Sql列数每个程序返回 T-Sql
【发布时间】:2015-05-12 19:56:07
【问题描述】:

我的任务是找出 sys.procedures 中每个程序 returns (selects) 有多少列? 程序看起来像

    Create PROCEDURE [dbo].[stpSSC_DMND001]
    @Event           nvarchar(3),    
    @FunctionalArea  nvarchar(10),
    @Venue           nvarchar(10)       
As

BEGIN  
    BEGIN TRY 

        If @Event is null or @Event=''
            RAISERROR('@Event can not be null or empty string',16,1);
        Else if not exists(select * from ENVIRONMENT where CODE=@Event)
            RAISERROR('Value "%s" for @Event not found in ENVIRONMENT',16,1, @Event);

        IF @FunctionalArea='All'
           Set @FunctionalArea=Null        

        IF @Venue='All'
           Set @Venue=Null
                SELECT DISTINCT ENV.NAME AS [Event],
                      ORG.CODE AS [FA code], 
                      ORG.NAMEAS [FA description],
                      LOC.CODE AS [Venue code]
                FROM 
                    POSITION AS POS
                    LEFT OUTER JOIN 
                    ENVIRONMENT AS ENV ON ENV.CODE = POS.EVENT
                WHERE ENV.CCODE_ENV=@Event
                      AND (@FunctionalArea IS NULL OR org.IDENTIFIER=@FunctionalArea)
                      AND (@Venue IS NULL OR loc.IDENTIFIER=@Venue)
                ORDER BY [FA code],
                         [Venue code]  
    END TRY

    /* ERROR HANDLING */
    BEGIN CATCH
        Declare @ErrMsg   nvarchar(200) = ERROR_MESSAGE(),
        RETURN @ErrNum;
   END CATCH
END

我在谷歌上找不到任何熟悉的东西。有什么建议?

【问题讨论】:

  • 你想out参数从程序返回?或者你有一个简单的选择查询并且你返回整个row
  • 没有输出参数。这只是简单的选择查询。我更新了问题。我需要列数。在这种情况下:tpRGM_SelectSport 2
  • 谢谢,但大多是程序要求输入参数,它们会带来很多数据。在我的情况下,执行程序不是一个好主意。

标签: sql sql-server sql-server-2008 tsql stored-procedures


【解决方案1】:

这在大多数情况下都有效,使用存储过程的静态分析,但也有一些存储过程不适用于:

SELECT
    procedures.name AS ProcedureName
    ,COUNT(*) AS FirstResultSetColumnCount
FROM 
    sys.procedures 
CROSS APPLY
(
    SELECT 1 as counter
    FROM sys.dm_exec_describe_first_result_set_for_object( procedures.object_id,1)
    WHERE error_state IS NULL
) metadata
GROUP BY procedures.name

编辑:请查看以下 MSDN 文章,了解函数 sys.dm_exec_describe_first_result_set_for_object 会返回错误代码的可能原因:

https://msdn.microsoft.com/en-us/library/ff878236.aspx

编辑:这将在您的道路上为您提供帮助,但这并不是您正在寻找的。如果您想使用 C#,我相信您可以使用 SqlDataReader 类(命名空间:System.Data.SqlClient / Assembly:System.Data)作为自动化解决方案。

DECLARE @ParameterInfo TABLE
(
    ProcedureId INT
    ,ProcedureName SYSNAME
    ,ParameterName SYSNAME
    ,TypeName SYSNAME
    ,UNIQUE(ProcedureName,ParameterName)
)

INSERT INTO @ParameterInfo 
SELECT 
    DENSE_RANK() OVER (ORDER BY procedures.object_id) AS procedureId
    ,procedures.name
    ,parameters.name
    ,types.name
FROM sys.procedures
JOIN sys.parameters
    ON procedures.object_id = parameters.object_id
JOIN sys.types
    ON parameters.user_type_id = types.user_type_id
where 
    has_default_value = 0
AND CAST(
 case 
 when procedures.is_ms_shipped = 1 then 1
 when (
    select 
        major_id 
    from 
        sys.extended_properties 
    where 
        major_id = procedures.object_id and 
        minor_id = 0 and 
        class = 1 and 
        name = N'microsoft_database_tools_support') 
    is not null then 1
 else 0
 end AS BIT) = 0

DECLARE @Counter INT = 1;
DECLARE @ProcedureCount INT = (SELECT MAX(ProcedureId) FROM @ParameterInfo);
DECLARE @ProcedureName  SYSNAME;
DECLARE @ParameterText  VARCHAR(MAX) = '';

WHILE @Counter <= @ProcedureCount
BEGIN

    SELECT
        @ProcedureName  = ProcedureName
        ,@ParameterText = 
            @ParameterText + ', ' 
            + ParameterName + ' = '
            + CASE
                TypeName
                WHEN 'INT' THEN '0'
                WHEN 'DATE' THEN '''1/1/1900'''
                WHEN 'DATETIME' THEN '''1/1/1900'''
                --More type defaults here...
                ELSE '0'
              END

    FROM
        @ParameterInfo
    WHERE 
        ProcedureID = @Counter 

    DECLARE @SQL VARCHAR(MAX) =  'SET FMTONLY ON; EXEC ' + @ProcedureName + SUBSTRING(@ParameterText,2,8000) + '; SET FMTONLY OFF;'

    PRINT @SQL;
    PRINT '---';

    SET @Counter = @Counter + 1;
END

编辑:或者您可以在本地机器上安装 SQLServer 2012 express 或开发人员版。

【讨论】:

  • 很高兴他们在 2012 年拥有它。但不幸的是,我使用的是 2008 R2。我没有在我的问题中定义它是我的错误。
  • 没问题。那么在这种情况下,最好的方法是在 FMTONLY 开启时“执行”每个存储过程。我将发布一个包含所有列号的示例的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多