【问题标题】:MSTSQL: Can a SP return both an out param and a result setMSTSQL:SP 能否同时返回输出参数和结果集
【发布时间】:2019-07-03 01:49:18
【问题描述】:

我想知道让 TSQL 存储过程同时返回结果集和输出参数是否可行。

create procedure uspReadMyXmlInformation(@myXmlDoc xml, @myProductNum varchar(18) output) as
    begin
        set nocount on;

        declare @myXmlContent table(MyOrderId varchar(12) not null
                                   ,CreatedAt datetime not null)

        insert into @myXmlContent
            select x.c.value('MyOrderID[1]', 'varchar(12)')
                    x.c.value('CreatedAt[1]', 'datetime')
                from @myXmlDoc.nodes('MyRootNodeName/MyChildNodeName') x(c)

        set @myProductNum='MyProductNum'

        select *
            from @myXmlContent

        return;
    end

所以,这里发生的情况是,我可以在删除输出参数时获得结果集,或者我获得输出参数并且结果集始终为空(0=count(*))。

我是否可以使用相同的存储过程获得两者,或者我最好将它们拆分?

我认为 Oracle 中的这篇文章是可行的。我想在 SQL Server 中实现同样的功能,但仅限于 2008 版本。

Oracle stored procedure: return both result set and out parameters

我喜欢使用同一个 SP 的原因是结果集和输出参数都代表了我从 XML 文档中读取的信息。所以,不知何故,SP 的名称说明了一切。

编辑

有些人认为它可能与以下内容重复:

Possible to return an out parameter with a DataReader

我不认为这与 DataReader 的行为方式相关的答案比 TSQL 的实现方式更重要。

事实是我从输出参数中得到了值,但我根本没有从结果集中得到它,它总是返回 null。

所以,我正在进行一个仅 SQL Server 的项目,我需要它。否则,如果不能及时实现,我就一分为二。

它的使用方法如下:

declare @xmlInformationData table(MyOrderId varchar(12) not null
                                  ,CreatedAt datetime not null)
insert into @xmlInformationData
    execute uspReadMyXmlInformation @myXmlDoc, @myProductNum output

while 0<(select count(*) from @xmlInformationData)
    begin
        -- This will never be executed because I have no rows in @xmlInformationData
        -- And yet, before the loop, I have my out param value!
    end

【问题讨论】:

  • 您可以同时拥有两者,但输出参数可能会“延迟”填充,例如在 .NET 应用程序中关闭 DataReader 后。
  • 正如@HABO 所说,您可以同时拥有两者,但out 变量通常仅在处理完最后一个结果集后才可用。
  • 其实根本没有DataReader!我不知道你们在哪里看到了 C# 标签之类的东西,但是没有!这是一个仅限 SQL Server 的项目,因为该数据库的目的是用作数据交换。因此,它从一边到另一边读取数据并推送信息。所以,周围没有 C# 代码!所以现在,我获得了输出参数值,但我从来没有获得结果集数据。而我两者都需要。有人可以帮忙吗?
  • @WillMarcouiller 您描述的问题通常发生在远程调用服务器时,这不是DataReader 的问题,而是由于用于与 SQL Server 通信的 TDS 协议的性质。当我在服务器 see screenshot 上运行查询时,我无法重现您的问题。

标签: tsql sql-server-2008 stored-procedures resultset output-parameter


【解决方案1】:

以下是同时使用输出参数和结果集的简单演示。尝试运行几次,结果应该会有所不同。

create procedure Arthur( @TheAnswer as Int Output ) as
  begin

  -- Set the value of the output parameter.
  set @TheAnswer = 42;

  -- Generate a single row most of the time.
  select GetDate() as NextVogonPoetryReading
    where DatePart( millisecond, GetDate() ) < 750;

  end;
go 1

-- Declare the variables for the test.
declare @HHGTTU as Table ( HHGTTUId Int Identity, NextVogonPoetryReading DateTime );
declare @SixTimesNine as Int;

-- Execute the SP once so that the   while   loop might.
insert into @HHGTTU ( NextVogonPoetryReading )
  execute Arthur @TheAnswer = @SixTimesNine Output;

-- See what happens.
while exists ( select Pi() from @HHGTTU )
  begin
  -- See where we are at.
  select @SixTimesNine as SixTimesNine, Max( HHGTTUId ) as MaxHHGTTUId, Max( NextVogonPoetryReading ) as MaxNextVogonPoetryReading
    from @HHGTTU;
  -- Reset.
  delete from @HHGTTU;
  set @SixTimesNine = 54;
  select @SixTimesNine as SixTimesNineAfterReset;
  waitfor delay '00:00:00.100';
  -- Execute the SP again.
  insert into @HHGTTU ( NextVogonPoetryReading )
    execute Arthur @TheAnswer = @SixTimesNine Output;
  end;

旁白:对于我提到 DataReader 给你的生活带来的创伤,我深表歉意。我只是试图传递我在 C# 应用程序中的经验,而没有深入了解您正在使用的数据库连接的具体类型、可能涉及哪些驱动程序……。

【讨论】:

  • 像你一样用“随机”结果进行测试似乎不太明智,因为 25% 的时间这将显示原始问题的“失败”测试用例。
  • @Lucero 目的是提供一个终止且具有不同行为的示例,包括有时返回零行,同时始终返回输出参数。它解决了 OP 帖子标题中的问题:“SP 能否同时返回输出参数和结果集”。它不能解决 OP 的问题,即“失败”的情况是只有一个或另一个输出似乎是可能的,但绝不可能两者兼而有之。
  • 很公平,我没有投反对票或其他任何事情,只是指出 0-row-result 在这里不是一个很好的例子。如果你想拥有“随机性”,像 1 或 2 行这样的东西会更好。 :)
  • 实际上我的问题是我有这个过程,返回一个结果集和一个输出参数,在 MSSQL 不太喜欢的第三层级上。相反,我不得不使用一个表值函数和一个单独的标量值函数。而且因为我不喜欢这种方式,所以我以不同的方式重构了我的代码,是的,现在我的uspReadXmlDataInformation 程序完美地返回了想要的信息。所以,故事的精神是不要超过两个嵌套的结果集 SP,否则会出现奇怪的行为。
猜你喜欢
  • 2013-07-24
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多