列出所有数据库的所有过程中引用的所有列

时间:2013-08-09 00:35:05

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

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

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

3 个答案:

答案 0 :(得分:3)

这将获得您所追踪的列表,但是如果您在动态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中)。

答案 1 :(得分:1)

列出所有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%' 

答案 2 :(得分:0)

这是另一种方法。这很脏,但我喜欢它。为什么?因为我提出来了。无论如何,它在动态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