检索存储过程的列名和类型?

时间:2013-01-29 02:38:55

标签: sql sql-server

  

可能重复:
  Retrieve column definition for stored procedure result set

我使用以下SQL获取表或视图的列名和类型:

DECLARE @viewname varchar (250);

select a.name as colname,b.name as typename 
from syscolumns a, systypes b -- GAH!
where a.id = object_id(@viewname) 
and a.xtype=b.xtype 
and b.name <> 'sysname'

如何为存储过程的输出列执行类似的操作?

2 个答案:

答案 0 :(得分:83)

[我刚刚意识到我answered this question before]

为存储过程执行此操作比查看视图或表格要复杂得多。其中一个问题是存储过程可能有多个不同的代码路径,具体取决于输入参数,甚至是你无法控制的东西,如服务器状态,时间等等。例如,你期望看到的输出是什么这个存储过程?如果有多个结果集而不考虑条件,该怎么办?

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

FMTONLY

一种方法是做这样的事情:

SET FMTONLY ON;
GO
EXEC dbo.bar;

这将为您提供一个空结果集,您的客户端应用程序可以查看该结果集的属性以确定列名和数据类型。

现在,SET FMTONLY ON;存在很多问题,我不会在这里讨论,但至少it should be noted that this command is deprecated - 有充分的理由。完成后还要小心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不显示长度,您必须获得其他类型的精确度/比例,例如datetime2timedecimal。但这是一个开始。

SQL Server 2012

SQL Server 2012中有一些新功能可以使元数据发现变得更加容易。对于上述过程,我们可以执行以下操作:

SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object
(
  OBJECT_ID('dbo.bar'), 
  NULL
);

除此之外,这实际上提供了精度和比例,并为我们解析了别名类型。对于上述过程,这会产生:

name   system_type_name
----   ----------------
a      varchar(1)
b      int
c      datetime

视觉上差别不大,但是当你开始进入具有不同精度和规模的所有不同数据类型时,你会欣赏这个功能为你做的额外工作。

缺点:在SQL Server 2012中,至少这些函数仅适用于第一个结果集(如函数名称所示)。

答案 1 :(得分:1)

您是否尝试返回所有存储过程及其所有参数?这样的事情应该适用于此。

select * from information_schema.parameters

如果您需要从存储过程返回列,请查看此处:

Get column names/types returned from a stored procedure