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

leo*_*leo 37 sql sql-server dependencies metadata

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

Mic*_*ito 50

我发现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;
Run Code Online (Sandbox Code Playgroud)

  • 好帖子,工作完美!还有一个补充,你必须检查对象是否是模式绑定,因为sp_refreshsqlmodule将给出错误否定,因为不支持模式绑定对象.因此,在查询中添加以下内容:and isnull(objectproperty(o.object_id,'IsSchemaBound'),0)= 0; (4认同)
  • 我还将第6行更改为`SELECT SCHEMA_NAME(o.schema_id)+'.['+ OBJECT_NAME(o.object_id)+']'`以防您在存储过程中使用名称中的点. (3认同)
  • 我在一个引用不存在的表的存储过程上尝试了这个脚本,但它没有突出显示它。果然,如果我只是运行 sp_refreshsqlmodule 'mysp' 它也不会报告此存储过程。 (3认同)
  • 刷新触发器的唯一方法是在未加密的情况下更改它们.(http://connect.microsoft.com/SQLServer/feedback/details/261905/sp-refreshsqlmodule-does-not-work-with-triggers).因此,上述脚本在遇到触发器时会产生误报 (2认同)

Cad*_*oux 8

It won't catch everything (dynamic SQL or latebound objects), but it can be useful - call sp_refreshsqlmodule on all non-schema bound stored procedures (you can call it before to ensure that dependencies are updated and then query the dependencies, or call it afterwards and see if anything is broken):

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
            )
Run Code Online (Sandbox Code Playgroud)


Dan*_*y G 7

我基本上做了同样的事情,但是将其编写为无游标,速度非常快。

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
Run Code Online (Sandbox Code Playgroud)

  • 使用 while 语句循环遍历数据表与使用带 fast_forward 的游标基本相同。两者都在痛苦地逐行进行(RBAR)。这是一种可以接受的情况,因为它不能被基于集合的操作替代。 (3认同)

Dan*_*and 6

除了 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
Run Code Online (Sandbox Code Playgroud)


Joh*_*ock 2

我想到的几种方法

  1. 最明显的方式运行程序
  2. 在删除表或字段之前检查表的依赖关系。然后检查那些依赖的过程
  3. 在所有过程上生成脚本并搜索该字段或表
  4. 查询系统对象