有没有一种方法可以获取实例中所有数据库中所有存储过程中引用的所有列和表?输出应该是:
Database Procedure Table Column
-------- --------- ----- ------
有没有一种方法可以获取实例中所有数据库中所有存储过程中引用的所有列和表?输出应该是:
Database Procedure Table Column
-------- --------- ----- ------
这将获得您所追求的列表,但是如果您在动态 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 中)。
列出所有 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%'
这是另一种方法。这很脏,但我喜欢它。为什么?因为我想出了它。无论如何,它在动态 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