【问题标题】:List all columns referenced in all procedures of all databases列出所有数据库的所有过程中引用的所有列
【发布时间】:2013-08-09 00:35:04
【问题描述】:

有没有一种方法可以获取实例中所有数据库的所有存储过程中引用的所有列和表?输出应该是:

Database   Procedure   Table   Column 
--------   ---------   -----   ------

【问题讨论】:

    标签: sql sql-server sql-server-2008 stored-procedures


    【解决方案1】:

    这将获得您所追求的列表,但是如果您在动态 SQL 中嵌入了此类列引用(并且可能找不到依赖延迟名称解析的引用),它将无济于事。 SQL Server 不解析存储过程的文本以提供 DMV 输出。

    现在尝试使用COLLATE 子句来处理您在同一台服务器上具有不同排序规则的数据库的情况。

    DECLARE @sql NVARCHAR(MAX) = N'';
    
    SELECT @sql += N'UNION ALL
    SELECT 
      [database]  = ''' + REPLACE(name, '''', '''''') + ''',
      [procedure] = QUOTENAME(s.name) + ''.'' + QUOTENAME(p.name)
                    COLLATE Latin1_General_CI_AI, 
      [table]     = QUOTENAME(referenced_schema_name) + ''.'' 
                  + QUOTENAME(referenced_entity_name)
                    COLLATE Latin1_General_CI_AI,
      [column]    = QUOTENAME(referenced_minor_name)
                    COLLATE Latin1_General_CI_AI
    FROM ' + QUOTENAME(name) + '.sys.schemas AS s
    INNER JOIN ' + QUOTENAME(name) + '.sys.procedures AS p
    ON s.[schema_id] = p.[schema_id]
    CROSS APPLY ' + QUOTENAME(name) 
    + '.sys.dm_sql_referenced_entities'
    + '(QUOTENAME(s.name) + ''.'' + QUOTENAME(p.name), N''OBJECT'') AS d
    WHERE d.referenced_minor_id > 0'
    FROM sys.databases 
      WHERE database_id > 4 
      AND [state] = 0;
    
    SET @sql = STUFF(@sql,1,11,'');
    
    EXEC sp_executesql @sql;
    

    如果您的数据库处于 80 兼容模式,CROSS APPLY 语法也将不起作用。只要确保您不在这样的数据库中执行代码,它应该可以正常工作(即使某些目标数据库在 80 中)。

    【讨论】:

    • 感谢亚伦的快速回复。当我执行该程序时,我遇到了一个错误,我试图理解和解决但无法解决。错误是 Msg 451, Level 16, State 1, Line 1 Cannot resolve collat​​ion conflict for column 2 in SELECT 语句。消息 451,级别 16,状态 1,行 1 无法解决 SELECT 语句中列 3 的排序规则冲突。消息 451,级别 16,状态 1,第 1 行无法解决 SELECT 语句中第 4 列的排序规则冲突。 ------------ 你能调查一下吗?
    • 您必须拥有具有不同排序规则的数据库。
    • 我收到错误 MSG 2020,这可能是由于“无法解析列依赖关系时发生的。此错误不会阻止查询返回对象级依赖关系。”我得到了输出,它闪烁了几秒钟,然后又出现了错误。
    • 我得到的实际错误是“为实体“[dbo].[MigrateExecutionLog] 报告的依赖项”不包括对列的引用。这要么是因为实体引用了不存在的对象,要么是因为实体中的一个或多个语句中的错误。在重新运行查询之前,请确保实体中没有错误并且该实体引用的所有对象都存在。我该如何解决这个问题。感谢亚伦的帮助。
    • @user2666339 听起来这只是identifying invalid column references in the stated stored procedure(s)。这可能是一件好事,尽管它目前正在阻碍你。
    【解决方案2】:

    列出所有包含指定列名的SP名称:

    SELECT OBJECT_NAME(M.object_id), M.* 
    FROM sys.sql_modules M 
    JOIN sys.procedures P 
    ON M.object_id = P.object_id 
    WHERE M.definition LIKE '%ColumnName%' 
    

    【讨论】:

    • 这可能会产生很多误报,具体取决于 ColumnName 是什么。它也只能在当前数据库中工作; OP 想要所有数据库。
    • 感谢塞尔瓦姆的回复。我需要所有存储过程中使用的所有列名。假设我们搜索列 ID,它可能会返回 ID 可能存在的所有存储过程,但它可能不会被用作列。如有错误请指正。
    【解决方案3】:

    这是另一种方法。这很脏,但我喜欢它。为什么?因为我想出了它。无论如何,它在动态 SQL 中使用动态 SQL 将依赖关系信息插入到可以查询的临时表中。

    这可以修改成一个SP,你可以不时运行更新依赖信息,临时表也可以更改为真实表,如果你想存储它。

    IF OBJECT_ID('tempdb.dbo.#SPDependencyDetails') IS NOT NULL
    DROP TABLE #SPDependencyDetails
    
    CREATE TABLE #SPDependencyDetails
    (
     Or_Object_Database NVARCHAR(128)
    ,Or_Object_Name NVARCHAR(128)
    ,Ref_Database_Name NVARCHAR(128)
    ,Ref_Schema_Name NVARCHAR(128)
    ,Ref_Object_Name NVARCHAR(128)
    ,Ref_Column_Name NVARCHAR(128)
    ,Is_Selected BIT
    ,Is_Updated BIT
    ,Is_Select_All BIT
    ,Is_All_Columns_Found BIT
    )
    
    DECLARE @database_name VARCHAR(100)
    
    DECLARE database_cursor CURSOR
    FOR
    SELECT name
        FROM sys.databases
        WHERE database_id > 4
    
    OPEN database_cursor
    
    FETCH NEXT FROM database_cursor
    INTO @database_name
    
    WHILE @@FETCH_STATUS = 0 --Outer Loop begin
    BEGIN
        DECLARE  @WholeLotofSQL NVARCHAR(MAX) =       '
        DECLARE @object_name VARCHAR(150)
        ,@sqlstatement NVARCHAR(2500)
    
        DECLARE object_cursor CURSOR --Inner cursor, iterates list of objects that match type
        FOR
            SELECT name
                FROM '+@database_name+'.sys.objects AS o
                WHERE o.type = ''P'' --Change Object type to find dependencies of Functions, Views and etc.
                ORDER BY 1    
    
        OPEN object_cursor
        FETCH NEXT FROM object_cursor INTO @object_name
    
        WHILE @@FETCH_STATUS = 0  --Inner Loop Begin
            BEGIN
                SET @sqlstatement = ''USE '+@database_name+';
    
                                    INSERT INTO #SPDependencyDetails
                                    SELECT DB_NAME() AS Or_Object_Database
                                            ,'''''' + @object_name + '''''' AS Or_Object_Name
                                            ,CASE WHEN referenced_database_name IS NULL THEN DB_NAME()
                                                    ELSE referenced_database_name
                                            END AS Ref_Database_Name
                                            ,referenced_schema_name AS Ref_Schema_Name
                                            ,referenced_entity_name AS Ref_Object_Name
                                            ,referenced_minor_name AS Ref_Column_Name
                                            ,is_selected
                                            ,is_updated
                                            ,is_select_all
                                            ,is_all_columns_found
                                        FROM sys.dm_sql_referenced_entities(''''dbo.'' + @object_name + '''''', ''''OBJECT'''');''
    
                EXEC sys.sp_executesql @sqlstatement
    
                FETCH NEXT FROM object_cursor INTO @object_name
            END      
        CLOSE object_cursor
        DEALLOCATE object_cursor'
    
        EXEC sys.sp_executesql @WholeLotofSQL
    
        FETCH NEXT FROM database_cursor INTO @database_name
    END
    
    CLOSE database_cursor;
    DEALLOCATE database_cursor;
    
    SELECT Or_Object_Database as 'Database'
    ,Or_Object_Name as 'Procedure'
    ,Ref_Object_Name as 'Table'
    ,Ref_Column_Name as 'Column
    FROM #SPDependencyDetails
    

    【讨论】:

      猜你喜欢
      • 2022-08-16
      • 2018-02-07
      • 1970-01-01
      • 2019-05-04
      • 2016-01-15
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      相关资源
      最近更新 更多