sql - T-SQL:我可以让 APPLY 在 CTE 上运行 TVF 吗?
问题描述
我正在为存储过程的工作编写一些文档。我能够创建一个列出存储过程使用的表和列的查询,但这是单数的,需要我将存储过程的名称作为参数传递。我在 SQL 文档中遇到了 APPLY,听起来它可以做我想做的事。
下面的代码似乎已经完成了一半;如果您将子查询t
替换n.name
为任何存储过程的名称,您将获得我想要的一个存储过程的输出。
with sprocnames as
(
select distinct name from sys.procedures
where name like '%sp%'
)
SELECT *
FROM sprocnames n outer apply
(
SELECT
n.name as SprocName
, referenced_id
, referenced_entity_name AS table_name
, referenced_minor_name as column_name
, is_all_columns_found
FROM sys.dm_sql_referenced_entities (n.name, 'OBJECT')
) as t
order by t.SprocName asc
所需的结果将是一个 SELECT,其中包含服务器上的每个存储过程以及每个使用的表和列的列表。
解决方案
你很亲密。事实上,如此接近,当您发现您的代码缺少什么时,您可能会面面相觑:模式名称。
您提供的名称sys.dm_sql_referenced_entities
应该是模式绑定的 - 即dbo.procedureName
。
这是一个工作版本:
WITH CTE AS
(
SELECT s.name +'.'+ n.name As FullName
FROM sys.procedures n
JOIN sys.schemas s
ON n.schema_id = s.schema_id
WHERE s.name LIKE '%sp%'
)
SELECT *
FROM CTE
CROSS APPLY (
SELECT
CTE.FullName as SprocName
, referenced_id
, referenced_entity_name AS table_name
, referenced_minor_name as column_name
, is_all_columns_found
FROM sys.dm_sql_referenced_entities (CTE.FullName, 'OBJECT')
) t
但是请注意,这也可能返回错误。事实上,当我在我的一个数据库上运行它时,我得到了以下错误(以及超过 900 行):
消息 2020,级别 16,状态 1,第 4 行为实体“dbo.sp_upgraddiagrams”报告的依赖关系可能不包括对所有列的引用。这要么是因为实体引用了一个不存在的对象,要么是因为实体中的一个或多个语句中的错误。在重新运行查询之前,请确保实体中没有错误并且该实体引用的所有对象都存在。
这让我想到了最后一点:您不应该sp_
为存储过程使用前缀。此前缀由 Microsoft 保留用于内置过程。
有关更多信息,请阅读 Aaron Bertrand 的“sp_ 前缀是否仍然是禁忌?
推荐阅读
- javascript - 如何选择css变量并将样式值分配给另一个元素
- magento2 - 将配置数据从本地环境迁移到生产 magento 2 的最佳方法是什么
- assembly - Windows 10 无法识别在 WINE 中工作的手工制作的 PE 可执行文件
- laravel - 为什么 Laravel 向我显示目录结构?
- android - Android 10 打开失败:PDF 的 ENOENT(没有这样的文件或目录)
- c# - Nunit中的assert消息中使用什么字符串格式传递args
- java - Java 中的 a[c - 'a' ]++ 是什么意思?
- r - 如何在 R 中改变具有中间结果、累积或减少的新列
- macos - 有没有办法清理 docker build 缓存?
- javascript - v-on 处理程序中的错误(Promise/async):TypeError:_this.$refs.editor.save 不是函数