[我刚刚意识到我之前回答过这个问题]
对于存储过程来说,做这件事情比视图或表要复杂得多。其中一个问题是,存储过程可以有多个不同的代码路径,这取决于输入参数,甚至包括你无法控制的东西,比如服务器状态、时间等等。例如,你期望看到这个存储过程的输出是什么?如果有多个结果集,无论条件如何呢?
CREATE PROCEDURE dbo.foo
@bar INT
AS
BEGIN
SET NOCOUNT ON;
IF @bar = 1
SELECT a, b, c FROM dbo.blat;
ELSE
SELECT d, e, f, g, h FROM dbo.splunge;
END
GO
如果您的存储过程没有代码路径,并且您确信始终会看到相同的结果集(并且可以预先确定如果存储过程具有非可选参数应提供什么值),让我们以一个简单的例子来说明:
CREATE PROCEDURE dbo.bar
AS
BEGIN
SET NOCOUNT ON;
SELECT a = 'a', b = 1, c = GETDATE();
END
GO
SQL Server 2012+
在SQL Server 2012中引入了一些新的函数,使元数据发现更加容易。对于上述过程,我们可以执行以下操作:
SELECT [column] = name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID('dbo.bar'),
NULL
);
除其他外,这实际上为我们提供了精度和规模,并解决了别名类型问题。对于以上过程,这产生了以下结果:
column system_type_name
------ ----------------
a varchar(1)
b int
c datetime
在视觉上没有太大区别,但当您开始涉及各种不同的数据类型、不同的精度和比例时,您会感谢这个函数为您做的额外工作。
缺点:到目前为止(通过 SQL Server 2022),这仅适用于第一个结果集(正如函数名称所示)。
FMTONLY
在旧版本中,一种方法是像这样做:
SET FMTONLY ON;
GO
EXEC dbo.bar;
这将给你一个空的结果集,你的客户端应用程序可以查看该结果集的属性以确定列名和数据类型。
现在,关于 SET FMTONLY ON; 存在很多问题,我不会在这里详细解释,但至少需要注意的是,这个命令已经被弃用了 - 有充分的理由。当你完成后,一定要小心地执行 SET FMTONLY OFF;,否则你会想知道为什么成功创建了存储过程,但无法执行它。不,我提醒你并不是因为我刚遇到了这个问题。诚实地说。:-)
OPENQUERY
通过创建一个环回链接服务器,然后使用像 OPENQUERY 这样的工具来执行存储过程,但返回可组合的结果集(请将其视为非常宽泛的定义),你可以检查结果集。首先创建一个环回服务器(假设本地实例名为 FOO):
USE master;
GO
EXEC sp_addlinkedserver @server = N'.\FOO', @srvproduct=N'SQL Server'
GO
EXEC sp_serveroption @server=N'.\FOO', @optname=N'data access',
@optvalue=N'true';
现在,我们可以将上述过程输入到以下查询中:
SELECT * INTO #t
FROM OPENQUERY([.\FOO], 'EXEC dbname.dbo.bar;')
WHERE 1 = 0;
SELECT c.name, t.name
FROM tempdb.sys.columns AS c
INNER JOIN sys.types AS t
ON c.system_type_id = t.system_type_id
WHERE c.[object_id] = OBJECT_ID('tempdb..#t');
这会忽略别名类型(以前称为用户定义数据类型),并且对于定义为 sysname 的列可能会显示两行。但从上面的内容中,它产生了以下结果:
name name
---- --------
b int
c datetime
a varchar
很明显这里还有更多的工作要做 - varchar 没有显示长度,你还需要获取其他类型的精度/比例,例如 datetime2、time 和 decimal。但这是一个开始。
RETURN SELECT * FROM OPENROWSET(TABLE DMF_SP_DESCRIBE_FIRST_RESULT_SET_OBJECT, @object_id, @browse_information_mode),但似乎不会执行。我唯一能让它工作的方法是在没有实际执行计划的查询窗口中直接运行它。 - Adam Plocher#TEMP表。 - Adam Plocher