Find broken objects in SQL Server

前端 未结 11 485
孤独总比滥情好
孤独总比滥情好 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:48

    I'm actually using sys.refreshmodule procedure now wrapped in a powershell script with the SQL Server Powershell add ins.

    This works better because this handy little sys function gets rid of the CREATE vs ALTER stuff. Some other answers here use this approach as well, but I prefer this one that's wrapped in Powershell and maybe some will find it useful.

    $server = "YourDBServer"
    cls
    Import-Module “sqlps” -DisableNameChecking
    
    $databases = Invoke-Sqlcmd -Query "select name from sys.databases where name not in ('master', 'tempdb', 'model', 'msdb')" -ServerInstance $server
    foreach ($db in $databases) {
        $dbName = $db.name
        $procedures = Invoke-Sqlcmd -Query "select SCHEMA_NAME(schema_id) as [schema], name from $dbName.sys.procedures" -ServerInstance $server
        foreach ($proc in $procedures) {
            if ($schema) {
                $shortName = $proc.schema + "." + $proc.name
                $procName =  $db.name + "." + $shortName
                try {
                    $result = Invoke-Sqlcmd -Database $dbName -Query "sys.sp_refreshsqlmodule '$shortName'" -ServerInstance $server -ErrorAction Stop
                    Write-Host "SUCCESS|$procName"
                }
                catch {
                    $msg = $_.Exception.Message.Replace([Environment]::NewLine, ",")
                    Write-Host "FAILED|$procName|$msg" -ForegroundColor Yellow
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 17:48

    As of SQL Server 2008, a much simpler method is here:

     SELECT OBJECT_NAME(referencing_id) AS 'object making reference' ,
           referenced_class_desc ,
           referenced_schema_name ,
           referenced_entity_name AS 'object name referenced' ,
           (   SELECT object_id
               FROM   sys.objects
               WHERE  name = [referenced_entity_name]
           ) AS 'Object Found?'
    FROM   sys.sql_expression_dependencies e
           LEFT JOIN sys.tables t ON e.referenced_entity_name = t.name;
    

    As mentioned in the source article (Microsoft MSDN Article on Finding Missing Dependencies), "A 'NULL' value in the 'Object Found?' column indicates the object was not found in sys.objects."

    Example output:

    ╔═══════════════════════════════════════════════╦═══════════════════════╦════════════════════════╦═══════════════════════════════════════╦═══════════════╗
    ║            object making reference            ║ referenced_class_desc ║ referenced_schema_name ║        object name referenced         ║ Object Found? ║
    ╠═══════════════════════════════════════════════╬═══════════════════════╬════════════════════════╬═══════════════════════════════════════╬═══════════════╣
    ║ usvConversationsWithoutServerNotices          ║ OBJECT_OR_COLUMN      ║ dbo                    ║ ConversationLinesWithID               ║ NULL          ║
    ║ usvFormattedConversationLines_WithSpeakerName ║ OBJECT_OR_COLUMN      ║ dbo                    ║ ConversationLinesWithID               ║ NULL          ║
    ║ usvFormattedConversationLines_WithSpeakerName ║ OBJECT_OR_COLUMN      ║ dbo                    ║ FormattedConversationLines_Cached     ║ NULL          ║
    ║ udpCheckForDuplicates                         ║ OBJECT_OR_COLUMN      ║ dbo                    ║ FormattedConversationLines_WithChatID ║ NULL          ║
    ║ usvFormattedConversationsCombined             ║ OBJECT_OR_COLUMN      ║ dbo                    ║ GROUP_CONCAT_D                        ║ 178099675     ║
    ║ usvSequenceCrossValidationSetStudents         ║ OBJECT_OR_COLUMN      ║ dbo                    ║ usvSequenceCrossValidationSet         ║ 1406628054    ║
    ╚═══════════════════════════════════════════════╩═══════════════════════╩════════════════════════╩═══════════════════════════════════════╩═══════════════╝
    

    If you get an error that says the subquery returned more than one value, then you have more than one object with the name equaling the [referenced_entity_name], and you will need the subquery to be more specific by adding another where clause.

    You can get more information by checking sys.objects, like this:

    SELECT *
    FROM   sys.objects
    WHERE  name = [referenced_entity_name]
    

    If that information alone isn't helpful enough to figure out how to distinguish your multiple results, you may need to join sys.objects to one of the other metadata views (which are mostly documented here: https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/object-catalog-views-transact-sql?view=sql-server-ver15 ) or to sys.schemas (documented here: https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/schemas-catalog-views-sys-schemas?view=sql-server-ver15 ) to get more information.

    0 讨论(0)
  • 2020-12-02 17:48

    Your best bet is to start using a tool like Visual Studio Database Edition. It's role is to manage a database schema. One of the many things it will do is to throw an error when you attempt to build the database project and it contains broken objects. It will of course do much more than this. The tool is free to any user of Visual Studio Team Suite or Visual Studio Developer Edition.

    0 讨论(0)
  • 2020-12-02 17:53

    Note the query in this thread finds missing objects, not invalid ones. 
    SQL Server doesn't find a referencing object is invalid until you execute it.

    Enhancement to that query to handle objects in other schemas as well as types:

    SELECT
        '[' + OBJECT_SCHEMA_NAME(referencing_id) + '].[' + OBJECT_NAME(referencing_id) + ']' 
            AS [this sproc, UDF or VIEW...],
        isnull('[' + referenced_schema_name + '].', '') + '[' + referenced_entity_name + ']' 
            AS [... depends ON this missing entity name]
    FROM 
        sys.sql_expression_dependencies
    WHERE 
        is_ambiguous = 0 AND 
        (
            (
                [referenced_class_desc] = 'TYPE' and 
                TYPE_ID(
                    isnull('[' + referenced_schema_name + '].', '') + 
                    '[' + referenced_entity_name + ']'
                ) IS NULL
            ) or
            (   
                [referenced_class_desc] <> 'TYPE' and 
                OBJECT_ID(
                    isnull('[' + referenced_schema_name + '].', '') + 
                    '[' + referenced_entity_name + ']'
                ) IS NULL
            )
        )
    ORDER BY 
        '[' + OBJECT_SCHEMA_NAME(referencing_id) + '].[' + OBJECT_NAME(referencing_id) + ']',
        isnull('[' + referenced_schema_name + '].', '') + '[' + referenced_entity_name + ']'
    
    0 讨论(0)
  • 2020-12-02 17:54

    Red Gate Software's SQL Prompt 5 has a Find Invalid Objects feature that might be useful in this situation. The tool goes through the database finding objects that will give an error when executed, which sounds exactly what you want.

    You can download a 14-day trial for free, so you can give it a try and see if it helps.

    Paul Stephenson
    SQL Prompt Project Manager
    Red Gate Software

    0 讨论(0)
  • First query will give you broken objects name includes Stored Procedure,View,Scalar function,DML trigger,Table-valued-function type

    /*
    /////////////
    ////ERROR////
    /////////////
    All error will be listed if object is broken
    */
    DECLARE @AllObjectName TABLE (
        OrdinalNo INT IDENTITY
        ,ObjectName NVARCHAR(MAX)
        ,ObjectType NVARCHAR(MAX)
        ,ErrorMessage NVARCHAR(MAX)
        )
    
    INSERT INTO @AllObjectName (
        ObjectName
        ,ObjectType
        )
    SELECT '[' + SCHEMA_NAME(schema_id) + '].[' + NAME + ']' ObjectName
        ,CASE [TYPE]
            WHEN 'P'
                THEN 'Stored Procedure'
            WHEN 'V'
                THEN 'View'
            WHEN 'FN'
                THEN 'Scalar function'
            WHEN 'TR'
                THEN 'DML trigger'
            WHEN 'TF'
                THEN 'Table-valued-function'
            ELSE 'Unknown Type'
            END
    FROM sys.objects
    WHERE [TYPE] IN (
            'P'
            ,'V'
            ,'FN'
            ,'TR'
            ,'TF'
            )
    ORDER BY NAME
    
    DECLARE @i INT = 1
    DECLARE @RowCount INT = (
            SELECT count(1)
            FROM @AllObjectName
            )
    DECLARE @ObjectName VARCHAR(MAX)
    
    WHILE @i <= @RowCount
    BEGIN
        BEGIN TRY
            SET @ObjectName = (
                    SELECT ObjectName
                    FROM @AllObjectName
                    WHERE OrdinalNo = @i
                    )
    
            EXEC sys.sp_refreshsqlmodule @ObjectName
        END TRY
    
        BEGIN CATCH
            DECLARE @message VARCHAR(4000)
                ,@xstate INT;
    
            SELECT @message = ERROR_MESSAGE()
                ,@xstate = XACT_STATE();
    
            IF @xstate = - 1
                ROLLBACK;
    
            UPDATE @AllObjectName
            SET ErrorMessage = @message
            WHERE OrdinalNo = @i
        END CATCH
    
        SET @i = @i + 1
    END
    
    SELECT ObjectName
        ,ObjectType
        ,ErrorMessage
    FROM @AllObjectName
    WHERE ErrorMessage IS NOT NULL
    

    And the below one search for unresolved references .. Generally which treated as warning, is still may cause error sometime

    /*
    /////////////
    ///Warning///
    /////////////
    Here all warning will come if object reference is not stated properly
    */
    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
    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]
    

    Thanks @SQLMonger .. for providing me the clue to make the First query which was my actual requirement

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