我想编写一个查询来查找数据库中尚未使用的所有过程。
我有一段代码列出了数据库中的所有程序:
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
现在我想把两者结合起来。首先获取所有过程的列表,然后通过第二个片段中的代码运行它。最后,列出那些没有返回结果的那些(或者在技术上,那些返回一个结果的那些,因为过程的名称将始终出现在过程的定义中)。
现在我创建列表(第一个片段)并检查它是否可以在任何地方访问(第二个片段),但我是手动完成的。我该如何实现自动化?
答案 0 :(得分:1)
您可以使用CROSS APPLY
。 APPLY
运算符允许您为查询的外表表达式返回的每一行调用表值函数。
你可以试试这个:
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;
答案 1 :(得分:0)
如果您只想在第二个查询中迭代第一个查询的结果,则可以创建别名并将其反馈。例如:
;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
或类似的东西。如果你想要数字,你也可以坚持第二个选择条款(因为我想这将返回很多结果)。
答案 2 :(得分:0)
要获取仅使用过程的列表,我稍微修改了 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
如果过程的名称仅在过程声明中出现 - 那么数据库中没有对此过程的其他引用。