2

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

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

3 回答 3

4

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

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

于 2013-08-09T00:52:14.023 回答
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%' 
于 2013-08-09T05:16:04.620 回答
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
于 2013-12-11T16:19:13.617 回答