列数每个过程返回T-Sql

时间:2015-03-11 06:01:38

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

我有一项任务是找出 sys.procedures 中每个程序返回选择)的列数? 程序看起来像

    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

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

1 个答案:

答案 0 :(得分:0)

这大部分时间都是使用存储过程的静态分析,但是有一些存储过程不适用于:

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返回error_code的可能原因:

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

编辑:这将帮助您前进,但它并不完全符合您的要求。如果你想使用C#,我相信你可以使用SqlDataReader类(Namespace: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或开发人员版本。