2010-06-12 90 views

回答

2

夫妇的我想到你删除表或现场之前

  1. 最明显的方法这个表上运行的程序
  2. 检查依赖的方式。再看看那些依赖proceudres
  3. 产生的所有程序脚本,并搜索字段或表
  4. 查询系统对象
6

它没有捕捉一切(动态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 
      ) 
+1

看来sp_refreshsqlmodule [可最终却刷新了错误的模块!(https://connect.microsoft.com/SQLServer/feedback/details/656863/sp-refreshsqlmodule-corrupts-renamed-objects-definitions ) – 2011-04-01 19:59:17

+0

@Martin是的,我应该提到这一点。在我的情况下,因为它是一个ALTER,并没有另一个过程使用相同的名称,我得到了一个错误,它没有任何伤害。 – 2011-04-02 15:45:20

42

我找到凯德回答我们eful在制定自己的脚本在数据库中检查的对象,所以我想我会分享我的剧本,以及:

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; 
+2

刷新触发器的唯一方法是在未加密的情况下更改它们。 (http://connect.microsoft.com/SQLServer/feedback/details/261905/sp-refreshsqlmodule-does-not-work-with-triggers)。因此,上面的脚本在遇到触发时会产生误报 – buckley 2012-02-16 09:22:09

+0

这对我来说非常合适。 (虽然我没有任何触发器) – ClearCloud8 2014-05-29 21:10:21

+4

好帖子,作品完美!还有一点,您必须检查对象是否与模式绑定,因为不支持模式绑定对象,sp_refreshsqlmodule会给出错误否定。因此,添加到您的查询以下:和 \t isnull(objectproperty(o.object_id,'IsSchemaBound'),0)= 0 \t; – 2014-09-05 19:41:15

2

除了迈克尔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 
+0

问题是它仍然会返回CTE别名和临时表作为空引用。 – 2017-06-29 17:32:08

1

我试过“凯德鲁”的回答,出了问题,我修好了如下

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;' 
+0

请格式化代码。 – rajuGT 2015-10-01 15:35:16

3

我基本上做同样的事情,但写它来是超快的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 
+1

使用while语句遍历数据表基本上与使用fast_forward的游标相同。两个人都在排队(RBAR)。这是一种可接受的情况,因为它不能被基于集合的操作取代。 – Nicholas 2016-01-12 03:50:23

+0

游标不是很高效。他们是记忆猪。 – 2016-01-15 02:37:03

+0

这比使用游标执行得更好一些,即使它仍然使用while循环。 – 2016-02-18 14:17:05

相关问题