Find broken objects in SQL Server

前端 未结 11 486
孤独总比滥情好
孤独总比滥情好 2020-12-02 17:26

Is there a tool that will find all objects in SQL Server (functions, procs, views) that cannot possibly work because they refer to objects that don\'t exist?

相关标签:
11条回答
  • 2020-12-02 17:59

    You may be interested in checking out the following articles:

    • Michael J. Swart: Find Missing SQL Dependencies
    • eggheadcafe.com: Find broken stuff

    You can test Michael J. Swart's solution as follows:

    CREATE PROCEDURE proc_bad AS
        SELECT col FROM nonexisting_table
    GO
    
    SELECT
        OBJECT_NAME(referencing_id) AS [this sproc or VIEW...],
        referenced_entity_name AS [... depends ON this missing entity name]
    FROM 
        sys.sql_expression_dependencies
    WHERE 
        is_ambiguous = 0
        AND OBJECT_ID(referenced_entity_name) IS NULL
    ORDER BY 
        OBJECT_NAME(referencing_id), referenced_entity_name;
    

    Which returns:

    +------------------------+------------------------------------------+
    | this sproc or VIEW...  |  ... depends ON this missing entity name |
    |------------------------+------------------------------------------|
    | proc_bad               |  nonexisting_table                       |
    +------------------------+------------------------------------------+
    
    0 讨论(0)
  • 2020-12-02 18:02

    The two previous solutions here are interesting, but both failed on my test databases.

    The original Michael J Swart script produced a huge number of false positives for me, far too many to wade through. Rick V.'s solution here was better - the only false positives it gave were for cross-database references.

    There's a comment on the Michael J Swart article by RaduSun which gives a solution that I can't yet break though! This is it, tweaked mildly for readability and my purposes, but credit to RaduSun for the logic.

    SELECT 
        QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.' 
            + QuoteName(OBJECT_NAME(referencing_id)) AS ProblemObject,
        o.type_desc,
        ISNULL(QuoteName(referenced_server_name) + '.', '')
        + ISNULL(QuoteName(referenced_database_name) + '.', '')
        + ISNULL(QuoteName(referenced_schema_name) + '.', '')
        + QuoteName(referenced_entity_name) AS MissingReferencedObject
    FROM
        sys.sql_expression_dependencies sed
            LEFT JOIN sys.objects o
                ON sed.referencing_id=o.object_id
    WHERE
        (is_ambiguous = 0)
        AND (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '')
        + ISNULL(QuoteName(referenced_database_name) + '.', '')
        + ISNULL(QuoteName(referenced_schema_name) + '.', '')
        + QuoteName(referenced_entity_name)) IS NULL)
    ORDER BY
        ProblemObject,
        MissingReferencedObject
    
    0 讨论(0)
  • 2020-12-02 18:02
     create table #BrokenObjects (Name nvarchar(500), Error nvarchar(max))
     select * into #objects from(
     select name from sys.views
     union select name from sys.procedures
     union select name from sys.tables
     )x
     declare @name nvarchar(500),@err nvarchar(max)
     while exists(select top 1 * from #objects)
     begin
     select top 1 @name = name from #objects
     begin try
     EXEC sys.sp_refreshsqlmodule @name
     end try
     begin catch
     select @err = ERROR_MESSAGE()
     insert into #BrokenObjects (name,error) values (@name,@err)
     end catch
     delete from #objects
     where name = @name
     end
     drop table #objects
     select * from #BrokenObjects
     where Error not like 'Could not find object % or you do not have permission.'
    
     drop table #BrokenObjects
    
    0 讨论(0)
  • 2020-12-02 18:05
    /*
    modified version of script from http://michaeljswart.com/2009/12/find-missing-sql-dependencies/
    Added columns for object types & generated refresh module command...
    filter out user-define types: http://stackoverflow.com/questions/2330521/find-broken-objects-in-sql-server
    

    */

    SELECT TOP (100) PERCENT
        QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.' + QuoteName(OBJECT_NAME(referencing_id)) AS [this Object...],
            o.type_desc,
        ISNULL(QuoteName(referenced_server_name) + '.', '')
        + ISNULL(QuoteName(referenced_database_name) + '.', '')
        + ISNULL(QuoteName(referenced_schema_name) + '.', '')
        + QuoteName(referenced_entity_name) AS [... depends ON this missing entity name]
        ,sed.referenced_class_desc
        ,case when o.type_desc in( 'SQL_STORED_PROCEDURE' ,'SQL_SCALAR_FUNCTION' ,'SQL_TRIGGER' ,'VIEW')
              then 'EXEC sys.sp_refreshsqlmodule ''' + QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.' + QuoteName(OBJECT_NAME(referencing_id)) + ''';'
              else null
           end as [Refresh SQL Module command]
    FROM sys.sql_expression_dependencies as sed
    LEFT JOIN sys.objects o
                ON sed.referencing_id=o.object_id
    WHERE (is_ambiguous = 0)
    AND (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '')
        + ISNULL(QuoteName(referenced_database_name) + '.', '')
        + ISNULL(QuoteName(referenced_schema_name) + '.', '')
        + QuoteName(referenced_entity_name)) IS NULL)
    AND NOT EXISTS
       (SELECT * 
        FROM sys.types 
        WHERE types.name = referenced_entity_name 
        AND types.schema_id = ISNULL(SCHEMA_ID(referenced_schema_name), SCHEMA_ID('dbo'))
       )
    ORDER BY [this Object...],
    [... depends ON this missing entity name]
    
    0 讨论(0)
  • 2020-12-02 18:06

    I wrote a script some years ago that will find Stored Procedures that won't compile by pulling the text of the proc and attempting to recompile it with a try/catch block. It's pretty simple and effective at finding at least procedures that can be dropped. You could easily expand it for views.

    Note that you should only run this against a DEV or TEST environment since it's actually attempting to recompile the procedures.

    SET NOCOUNT ON
    
    DECLARE @ProcedureName VARCHAR(2048)
    DECLARE @ProcedureBody VARCHAR(MAX)
    
    DECLARE @RoutineName varchar(500)
    
    DECLARE procCursor CURSOR STATIC FORWARD_ONLY READ_ONLY
     FOR
     SELECT
     --TOP 1
     SCHEMA_NAME(schema_id) + '.' + NAME AS ProcedureName,
     OBJECT_DEFINITION(o.[object_id]) AS ProcedureBody
     FROM sys.objects AS o
     WHERE o.[type] = 'P'
     ORDER BY o.[name]
    
    OPEN procCursor
    FETCH NEXT FROM procCursor INTO @ProcedureName, @ProcedureBody
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
     -- Might have to play with this logic if you don't have discipline in your create statements
     SET @ProcedureBody = REPLACE(@ProcedureBody, 'CREATE PROCEDURE', 'ALTER PROCEDURE')
    
     BEGIN TRY
       EXECUTE(@ProcedureBody)
       PRINT @ProcedureName + ' -- Succeeded'
     END TRY
     BEGIN CATCH
       PRINT @ProcedureName + ' -- Failed: ' + ERROR_MESSAGE()
     END CATCH
    
     FETCH NEXT FROM procCursor INTO @ProcedureName, @ProcedureBody
    END
    
    CLOSE procCursor
    DEALLOCATE procCursor
    

    https://brettwgreen.wordpress.com/2012/12/04/find-stored-procedures-that-wont-compile/

    0 讨论(0)
提交回复
热议问题