查询服务器未使用的过程
Query server for unused procedures
我想编写一个查询来查找数据库中所有未使用的过程。
我有一段代码列出了数据库中的所有过程:
SELECT p.name AS 'SP Name'
FROM sys.procedures AS p
WHERE p.is_ms_shipped = 0
ORDER BY p.name
我还有另一段代码,用于检查表达式是否在现有过程中的任何地方使用:
declare @expression nvarchar(100) = '%sp_myProcedure%'
SELECT DISTINCT
o.name AS Object_Name,
o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o
ON m.object_id=o.object_id
WHERE m.definition Like @expression
现在我想把两者结合起来。首先获取所有程序的列表,然后 运行 通过第二个代码段中的代码获取它。最后,列出没有返回结果的那些(或者从技术上讲,那些返回一个结果的,因为过程的名称将始终出现在过程的定义中)。
现在我创建了列表(第一个片段)并检查它是否在任何地方都可以访问(第二个片段),但我是手动完成的。我怎样才能使它自动化?
您可以使用 CROSS APPLY
。 APPLY
运算符允许您为查询的外部 table 表达式返回的每一行调用一个 table 值函数。
你可以试试这个:
SELECT P.name AS 'SP Name'
,TU.Object_Name
FROM sys.procedures AS P
CROSS APPLY (SELECT DISTINCT O.name AS Object_Name
,O.type_desc
FROM sys.sql_modules AS M
INNER JOIN sys.objects AS O
ON M.object_id = O.object_id
WHERE M.definition LIKE '%' + P.name + '%') AS TU
WHERE P.is_ms_shipped = 0
ORDER BY P.name;
如果您只想在第二个查询中迭代第一个查询的结果,您可以创建一个别名并将其传递。例如:
;with prc_names as (SELECT p.name AS sp_name
FROM sys.procedures AS p
WHERE p.is_ms_shipped = 0)
SELECT
p.sp_name as 'SP Name',
o.name AS Object_Name,
o.type_desc
FROM sys.sql_modules m, prc_names p
INNER JOIN sys.objects o
ON m.object_id=o.object_id
WHERE m.definition Like p.sp_name
group by p.sp_name, o.name, o.type_desc
order by p.sp_name
或类似的东西。如果你想要数字,你也可以在第二个 select 子句上计数(我想这会 return 很多结果)。
为了获得未使用程序的列表,我稍微修改了 king.code 的(非常有帮助的)解决方案:
-- List only unused procedures
SELECT v.SP_Name FROM
(SELECT P.name AS SP_Name ,TU.Object_Name
FROM sys.procedures AS P
CROSS APPLY (SELECT DISTINCT O.name AS Object_Name
,O.type_desc
FROM sys.sql_modules AS M
INNER JOIN sys.objects AS O
ON M.object_id = O.object_id
WHERE M.definition LIKE '%' + P.name + '%') AS TU
WHERE P.is_ms_shipped = 0) v
GROUP BY v.SP_Name
HAVING COUNT(v.SP_Name) <= 1
如果过程的名称只在过程声明中出现一次,那么数据库中没有其他对此过程的引用。
我想编写一个查询来查找数据库中所有未使用的过程。
我有一段代码列出了数据库中的所有过程:
SELECT p.name AS 'SP Name'
FROM sys.procedures AS p
WHERE p.is_ms_shipped = 0
ORDER BY p.name
我还有另一段代码,用于检查表达式是否在现有过程中的任何地方使用:
declare @expression nvarchar(100) = '%sp_myProcedure%'
SELECT DISTINCT
o.name AS Object_Name,
o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o
ON m.object_id=o.object_id
WHERE m.definition Like @expression
现在我想把两者结合起来。首先获取所有程序的列表,然后 运行 通过第二个代码段中的代码获取它。最后,列出没有返回结果的那些(或者从技术上讲,那些返回一个结果的,因为过程的名称将始终出现在过程的定义中)。
现在我创建了列表(第一个片段)并检查它是否在任何地方都可以访问(第二个片段),但我是手动完成的。我怎样才能使它自动化?
您可以使用 CROSS APPLY
。 APPLY
运算符允许您为查询的外部 table 表达式返回的每一行调用一个 table 值函数。
你可以试试这个:
SELECT P.name AS 'SP Name'
,TU.Object_Name
FROM sys.procedures AS P
CROSS APPLY (SELECT DISTINCT O.name AS Object_Name
,O.type_desc
FROM sys.sql_modules AS M
INNER JOIN sys.objects AS O
ON M.object_id = O.object_id
WHERE M.definition LIKE '%' + P.name + '%') AS TU
WHERE P.is_ms_shipped = 0
ORDER BY P.name;
如果您只想在第二个查询中迭代第一个查询的结果,您可以创建一个别名并将其传递。例如:
;with prc_names as (SELECT p.name AS sp_name
FROM sys.procedures AS p
WHERE p.is_ms_shipped = 0)
SELECT
p.sp_name as 'SP Name',
o.name AS Object_Name,
o.type_desc
FROM sys.sql_modules m, prc_names p
INNER JOIN sys.objects o
ON m.object_id=o.object_id
WHERE m.definition Like p.sp_name
group by p.sp_name, o.name, o.type_desc
order by p.sp_name
或类似的东西。如果你想要数字,你也可以在第二个 select 子句上计数(我想这会 return 很多结果)。
为了获得未使用程序的列表,我稍微修改了 king.code 的(非常有帮助的)解决方案:
-- List only unused procedures
SELECT v.SP_Name FROM
(SELECT P.name AS SP_Name ,TU.Object_Name
FROM sys.procedures AS P
CROSS APPLY (SELECT DISTINCT O.name AS Object_Name
,O.type_desc
FROM sys.sql_modules AS M
INNER JOIN sys.objects AS O
ON M.object_id = O.object_id
WHERE M.definition LIKE '%' + P.name + '%') AS TU
WHERE P.is_ms_shipped = 0) v
GROUP BY v.SP_Name
HAVING COUNT(v.SP_Name) <= 1
如果过程的名称只在过程声明中出现一次,那么数据库中没有其他对此过程的引用。