如何在sql server中检查所有存储过程是否正常?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在sql server中检查所有存储过程是否正常?相关的知识,希望对你有一定的参考价值。

如果我删除一个或多个表,如何在sql server中检查所有存储过程是否正常?

答案

我发现Cade的答案在制定我自己的脚本以检查数据库中的对象时很有用,所以我想我也会分享我的脚本:

DECLARE @Name nvarchar(1000);
DECLARE @Sql nvarchar(1000);
DECLARE @Result int;

DECLARE ObjectCursor CURSOR FAST_FORWARD FOR
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id))
FROM sys.objects o
WHERE type_desc IN (
'SQL_STORED_PROCEDURE',
'SQL_TRIGGER',
'SQL_SCALAR_FUNCTION',
'SQL_TABLE_VALUED_FUNCTION',
'SQL_INLINE_TABLE_VALUED_FUNCTION',
'VIEW')
    --include the following if you have schema bound objects since they are not supported
    AND ISNULL(OBJECTPROPERTY(o.object_id, 'IsSchemaBound'), 0) = 0
;

OPEN ObjectCursor;

FETCH NEXT FROM ObjectCursor INTO @Name;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @Sql = N'EXEC sp_refreshsqlmodule ''' + @Name + '''';
    --PRINT @Sql;

    BEGIN TRY
        EXEC @Result = sp_executesql @Sql;
        IF @Result <> 0 RAISERROR('Failed', 16, 1);
    END TRY
    BEGIN CATCH
        PRINT 'The module ''' + @Name + ''' does not compile.';
        IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    END CATCH

    FETCH NEXT FROM ObjectCursor INTO @Name;
END

CLOSE ObjectCursor;
DEALLOCATE ObjectCursor;
另一答案

我的方法有点不同。我在SSMS中为一堆proc创建了alter script,然后等了几秒钟,所以SSMS处理它们并得到了我想要的东西:

enter image description here

然后,对于任何错误的行,SSMS右边界一个红点,我可以轻松检查,纠正并稍后执行相同的脚本以更新正确的值。

另一答案

它不会捕获所有内容(动态SQL或后向对象),但它可能很有用 - 在所有非模式绑定存储过程上调用sp_refreshsqlmodule(您可以先调用它以确保更新依赖项,然后查询依赖项,或调用之后再看看是否有任何损坏):

DECLARE @template AS varchar(max)
SET @template = 'PRINT ''{OBJECT_NAME}''
EXEC sp_refreshsqlmodule ''{OBJECT_NAME}''

'

DECLARE @sql AS varchar(max)

SELECT  @sql = ISNULL(@sql, '') + REPLACE(@template, '{OBJECT_NAME}',
                                          QUOTENAME(ROUTINE_SCHEMA) + '.'
                                          + QUOTENAME(ROUTINE_NAME))
FROM    INFORMATION_SCHEMA.ROUTINES
WHERE   OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.'
                                 + QUOTENAME(ROUTINE_NAME)),
                       N'IsSchemaBound') IS NULL
        OR OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.'
                                    + QUOTENAME(ROUTINE_NAME)),
                          N'IsSchemaBound') = 0

        EXEC (
              @sql
            )
另一答案

我基本上做了同样的事情,但把它写成了CURSORless,这是超级快的。

DECLARE @Name nvarchar(1000);
DECLARE @Sql nvarchar(1000);
DECLARE @Result int;

DECLARE @Objects TABLE (
    Id INT IDENTITY(1,1),
    Name nvarchar(1000)
)

INSERT INTO @Objects
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id))
FROM sys.objects o
WHERE type_desc IN (
'SQL_STORED_PROCEDURE',
'SQL_TRIGGER',
'SQL_SCALAR_FUNCTION',
'SQL_TABLE_VALUED_FUNCTION',
'SQL_INLINE_TABLE_VALUED_FUNCTION',
'VIEW')
    --include the following if you have schema bound objects since they are not supported
    AND ISNULL(OBJECTPROPERTY(o.object_id, 'IsSchemaBound'), 0) = 0

DECLARE @x INT
DECLARE @xMax INT

SELECT @xMax = MAX(Id) FROM @Objects
SET @x = 1

WHILE @x < @xMax
BEGIN
    SELECT @Name = Name FROM @Objects WHERE Id = @x

    SET @Sql = N'EXEC sp_refreshsqlmodule ''' + @Name + '''';
    --PRINT @Sql;

    BEGIN TRY
        EXEC @Result = sp_executesql @Sql;
        IF @Result <> 0 RAISERROR('Failed', 16, 1);
    END TRY
    BEGIN CATCH
        PRINT 'The module ''' + @Name + ''' does not compile.';
        IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    END CATCH
    SET @x = @x + 1
END
另一答案

除了Michael Petito的脚本之外,您还可以检查SP中延迟绑定对象的问题(延迟名称解析),如下所示:

-- Based on comment from http://blogs.msdn.com/b/askjay/archive/2012/07/22/finding-missing-dependencies.aspx
-- Check also http://technet.microsoft.com/en-us/library/bb677315(v=sql.110).aspx

select o.type, o.name, ed.referenced_entity_name, ed.is_caller_dependent
from sys.sql_expression_dependencies ed
join sys.objects o on ed.referencing_id = o.object_id
where ed.referenced_id is null
另一答案

想到几种方式

  1. 最明显的方式是运行程序
  2. 删除表或字段之前检查表上的依赖项。然后查看那些依赖程序
  3. 在所有过程上生成脚本并搜索该字段或表
  4. 查询sysobjects
另一答案

我尝试了“Cade Roux”答案,它出错了,我把它修好如下

 SELECT 'BEGIN TRAN T1;' UNION
    SELECT   REPLACE('BEGIN TRY
    EXEC sp_refreshsqlmodule ''{OBJECT_NAME}''
      END TRY
      BEGIN CATCH
    PRINT ''{OBJECT_NAME} IS INVALID.'' 
     END CATCH', '{OBJECT_NAME}',
                                              QUOTENAME(ROUTINE_SCHEMA) + '.'
                                              + QUOTENAME(ROUTINE_NAME))
    FROM    INFORMATION_SCHEMA.ROUTINES
    WHERE   OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.'
                                     + QUOTENAME(ROUTINE_NAME)),
                           N'IsSchemaBound') IS NULL
            OR OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.'
                                        + QUOTENAME(ROUTINE_NAME)),
                              N'IsSchemaBound') = 0
                              UNION 
                            SELECT  'ROLLBACK TRAN T1;'
另一答案

给出的答案都没有找到因重命名或删除表而导致的错误但是很开心,我有一个解决方案:

DECLARE @NumberRecords INT
DECLARE @RowCount INT
DECLARE @Name NVARCHAR(MAX)
DECLARE @Command NVARCHAR(MAX)
DECLARE @Result int
DECLARE @Names TABLE (
    [RowId] INT NOT NULL    IDENTITY(1, 1),
    [Name]  NVARCHAR(MAX),
    [Type]  NVARCHAR(MAX)
)

INSERT INTO @Names
SELECT
        QUOTENAME(SCHEMA_NAME([Objects].schema_id)) + '.' + QUOTENAME(OBJECT_NAME([Objects].object_id)) [Name],
        type_desc [Type]
FROM sys.objects [Objects]
WHERE type_desc IN ('SQL_STORED_PROCEDURE',
                    'SQL_TRIGGER',
                    'SQL_SCALAR_FUNCTION',
                    'SQL_TABLE_VALUED_FUNCTION',
                    'SQL_INLINE_TABLE_VALUED_FUNCTION',
                    'VIEW')
ORDER BY [Name]

SET @RowCount = 1
SET @NumberRecords = (SELECT COUNT(*) FROM @Names)
WHILE (@RowCount <= @NumberRecords)
BEGIN

    SELECT @Name = [Name]
    FROM @Names
    WHERE [RowId] = @RowCount

    SET @Command = N'EXEC sp_refreshsqlmodule ''' + @Name + ''''

    BEGIN TRY

        EXEC @Result = sp_executesql @Command

        IF @Result <> 0
        BEGIN

            RAISERROR('Failed', 16, 1)

        END
        ELSE
        BEGIN

            IF (NOT EXISTS (SELECT *
                            FROM sys.dm_sql_referenced_entities(@Name, 'OBJECT')
                            WHERE [is_incomplete] = 1))
            BEGIN

                DELETE
                FROM @Names
                WHERE [RowId] = @RowCount

            END

        END

    END TRY
    BEGIN CATCH

        -- Nothing

    END CATCH

    SET @RowCount = @RowCount + 1

END

SELECT  [Name],
        [Type]
FROM @Names
另一答案

同样的想法,但更通用 - 您使用实体检查所有用户定义的对象并在编译期间显示错误。重命名/删除对象/列等后,这非常有用

只需在数据库架构更新后运行它,以确保所有正文对象仍然有效

DECLARE @obj_name AS sysname, @obj_type AS sysname

DECLARE obj_cursor CURSOR FOR 
    SELECT SCHEMA_NAME(o.schema_id) + '.' + o.name, o.type_desc 
    FROM sys.objects o 
    INNER JOIN sys.sql_modules m ON o.object_id = m.object_id
    WHERE o.is_ms_shipped = 0 AND m.is_schema_bound = 0 
    ORDER BY o.type_desc, SCHEMA_NAME(o.schema_id), o.name

OPEN obj_cursor 
FETCH NEXT FROM obj_cursor INTO @obj_name, @obj_type

WHILE (@@FETCH_STATUS <> -1) 
BEGIN
    BEGIN TRY
        EXEC sp_refreshs

以上是关于如何在sql server中检查所有存储过程是否正常?的主要内容,如果未能解决你的问题,请参考以下文章