【问题标题】:get returned fields datatypes from a stored procedure从存储过程中获取返回的字段数据类型
【发布时间】:2014-08-28 13:38:29
【问题描述】:

我遇到了一个小问题。我想创建一个表单,要求输入过程名称并返回存储过程的参数和过程返回的列。

例如

 CREATE PROCEDURE abc 
    @Param1 int,
    @Param2 varchar(1)
 as
    SELECT * 
    FROM TableA 
    WHERE Param1 = @Param1 and Param2 = @Param2
 GO

我知道我可以使用此查询从 SQL Server 获取过程的参数

select  
   'Parameter_name' = name,  
   'Type'   = type_name(user_type_id),  
   'Length'   = max_length,  
   'Prec'   = case when type_name(system_type_id) = 'uniqueidentifier' 
              then precision  
              else OdbcPrec(system_type_id, max_length, precision) end,  
   'Scale'   = OdbcScale(system_type_id, scale),  
   'Param_order'  = parameter_id,  
   'Collation'   = convert(sysname, 
                   case when system_type_id in (35, 99, 167, 175, 231, 239)  
                   then ServerProperty('collation') end)  

  from sys.parameters where object_id = object_id('[dbo].[abc]')

根据我在网上阅读的内容,没有简单的方法可以从存储过程中获取返回的数据类型及其名称,因为根据输入参数,结果可能会有所不同。

我很想知道是否有办法从 SQL 中获取返回的数据类型及其名称,但我不介意是否有人可以告诉我,或者将我引导到可以找到解决方案的地方从 Delphi 返回的数据类型及其名称。就像您单击 TADOStoredProc 并单击 AddAllFields 选项时一样。

希望我能理解自己。

谢谢

【问题讨论】:

  • SET FMTONLY 对你有用吗?
  • 这似乎只适用于查询,我有 SP。
  • 问题是存储过程没有数据契约。 sql 引擎无法确定要返回的数据类型。考虑您的过程是否有一些条件,这些条件可能会根据参数返回不同的结果集。引擎如何知道将返回什么?简而言之,您尝试做的事情是不可能的。
  • @SeanLange 一个人可以评估存储过程中所有可能的路径,并检查它们是否都导致相同的记录集。如果是这样,您可以确定架构。 “sys.dm_exec_describe_first_result_set”和“sp_describe_first_result_set”就是这样做的。看我的回答。
  • 当然,如果您必须评估程序的内容,那么记录输出不是更容易吗?这是 OP 似乎试图避免的。当然,也不能保证程序在评估和运行时间之间不会发生变化。

标签: sql sql-server delphi stored-procedures


【解决方案1】:

您可以使用 sys.dm_exec_describe_first_result_set

参见示例 B“返回有关过程的信息”

USE AdventureWorks2012;
GO

CREATE PROC Production.TestProc
AS
SELECT Name, ProductID, Color FROM Production.Product ;
SELECT Name, SafetyStockLevel, SellStartDate FROM Production.Product ;
GO

SELECT * FROM sys.dm_exec_describe_first_result_set
('Production.TestProc', NULL, 0) ;

http://msdn.microsoft.com/en-us/library/ff878258.aspx#code-snippet-2

它使用与 sp_describe_first_result_set 相同的算法,因此您可以在以下位置找到一些说明:

http://msdn.microsoft.com/en-us/library/ff878602.aspx

【讨论】:

  • 谢谢,它适用于某些特殊情况,但我会坚持使用这种程序。
【解决方案2】:

这绝不是一个完整的答案,但我想展示如何使用SET FMTONLY。它可能会解决部分 OP 的请求。

CREATE PROCEDURE abc 
    @Param1 INT
AS
    SELECT TOP(@Param1) *
    FROM master.sys.objects
GO

--When set OFF, 3 rows are returned.
SET FMTONLY OFF
EXEC abc @Param1 = 3

--When set ON, no rows are returned, but the columns and column names of the result set are returned.
SET FMTONLY ON
EXEC abc @Param1 = 3

注意:如果存储过程有分支并且可能返回不同的结果集,则此选项不起作用。同样,这不是一个完整的答案,只是 OP 的演示。

【讨论】:

  • 还应该指出,SET FMTONLY 在 SQL 2012 中已被替换为更强大的功能。
  • 我会留下这个答案,以防 OP 使用的是“旧”版本。如果是 SQL 2012 或更高版本,我会选择@Caffé 的答案。
  • 我知道这不适用于分支,感谢您为我清理它!
  • @CiucaS DMason 展示的这种方法由 ADO 在检查表模式时使用,并且可能是 TADOStoredProc 组件使用的方法。您可以通过分析 ADO 执行的查询(使用 SQL Server 跟踪/配置文件)来了解 ADO 是如何发挥作用的。
  • 较旧的 SQLOLEDB ADO 提供程序使用 SET FMTONLY。较新的驱动程序(SQLNCLI11 和新的 MSOLEDBSQL)使用 sys.dm_exec_describe_first_result_set
【解决方案3】:

最好不要从一个存储过程返回许多不同的集合。如果必须返回许多集合,最好创建不同的过程并从每个过程中返回统一的数据集。一个过程的多个结果集不应该返回。仅仅因为某事是可能的,并不意味着它应该被利用。

【讨论】:

    猜你喜欢
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 2013-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多