37

我正在使用 SQL Server 2005,我想知道如何从 transact-sql 中访问不同的结果集。以下存储过程返回两个结果集,例如,如何从另一个存储过程访问它们?

CREATE PROCEDURE getOrder (@orderId as numeric) AS
BEGIN   
    select order_address, order_number from order_table where order_id = @orderId
    select item, number_of_items, cost from order_line where order_id = @orderId
END

我需要能够单独遍历两个结果集。

编辑:只是为了澄清问题,我想测试存储过程。我有一组从 VB.NET 客户端使用的存储过程,它们返回多个结果集。这些不会更改为表值函数,实际上我根本无法更改程序。改变程序不是一种选择。

过程返回的结果集不是相同的数据类型或列数。

4

7 回答 7

34

简短的回答是:你做不到。

从 T-SQL 中,如果不按照其他人的建议更改存储过程,就无法访​​问嵌套存储过程调用的多个结果。

完整地说,如果过程返回单个结果,您可以使用以下语法将其插入到临时表或表变量中:

INSERT INTO #Table (...columns...)
EXEC MySproc ...parameters...

您可以对返回多个结果的过程使用相同的语法,但它只会处理第一个结果,其余的将被丢弃。

于 2008-09-12T13:48:13.370 回答
8

通过创建一个包含内部数据集的 SQL2005 CLR 存储过程,我很容易做到这一点。

您会看到,一个新的 SqlDataAdapter 默认情况下会将一个多结果集存储过程填充到一个多表数据集中。这些表中的数据可以依次插入到您希望编写的调用存储过程中的#Temp 表中。 dataset.ReadXmlSchema将向您显示每个结果集的架构。

第 1 步:开始编写 sproc,它将从多结果集 sproc 中读取数据

一种。根据架构为每个结果集创建一个单独的表。

CREATE PROCEDURE [dbo].[usp_SF_Read] AS
SET NOCOUNT ON;
CREATE TABLE #Table01 (Document_ID VARCHAR(100)
  , Document_status_definition_uid INT
  , Document_status_Code VARCHAR(100) 
  , Attachment_count INT
  , PRIMARY KEY (Document_ID));

湾。此时您可能需要声明一个游标来重复调用您将在此处创建的 CLR 存储过程:

第 2 步:制作 CLR Sproc

Partial Public Class StoredProcedures
    <Microsoft.SqlServer.Server.SqlProcedure()> _
    Public Shared Sub usp_SF_ReadSFIntoTables()

    End Sub
End Class

一种。使用 连接New SqlConnection("context connection=true")

湾。设置一个命令对象 (cmd) 以包含多结果集存储过程。

C。使用以下命令获取所有数据:

    Dim dataset As DataSet = New DataSet
    With New SqlDataAdapter(cmd)
        .Fill(dataset) ' get all the data.
    End With
'you can use dataset.ReadXmlSchema at this point...

d。遍历每个表并将每一行插入适当的临时表(您在上面的第一步中创建)。

最后一点: 根据我的经验,您可能希望在表之间强制执行一些关系,以便知道每条记录来自哪个批次。

这就是它的全部!

〜肖恩,西雅图附近

于 2009-05-18T20:02:33.440 回答
5

你也可以做一些事情。将可选参数 N int 添加到您的存储过程中。默认值 N 为 -1。如果 N 的值为 -1,则执行您的每一项选择。否则,进行第 N 次选择,并且仅进行第 N 次选择。

例如,

if (N = -1 or N = 0)
    select ...

if (N = -1 or N = 1)
    select ...

未指定 N 的 sproc 调用者将获得包含多个表的结果集。如果您需要从另一个存储过程中提取这些表中的一个或多个,只需调用指定 N 值的存储过程即可。您必须为要提取的每个表调用存储过程一次。如果您需要来自结果集中的多个表,则效率低下,但它确实适用于纯 TSQL。

于 2011-08-23T22:21:28.563 回答
4

请注意,INSERT INTO ... EXEC 语句有一个额外的、未记录的限制:它不能嵌套。也就是说,EXEC 调用的存储过程(或它依次调用的任何过程)本身不能执行 INSERT INTO ... EXEC。似乎每个进程都有一个累积结果的暂存器,如果它们是嵌套的,当调用者打开它时你会得到一个错误,然后被调用者尝试再次打开它。

Matthieu,您需要为每种“类型”的结果维护单独的临时表。此外,如果您多次执行相同的操作,您可能需要在该结果中添加一个额外的列,以指示它来自哪个调用。

于 2008-09-15T21:52:05.883 回答
2

遗憾的是,不可能做到这一点。当然,问题是没有允许它的 SQL 语法。当然,它发生在“幕后”,但是您无法在 TSQL 中获得这些其他结果,只能通过 ODBC 或其他方式从应用程序中获得。

与大多数事情一样,有一种方法可以绕过它。诀窍是在 TSQL 中使用 ole 自动化来创建一个 ADODB 对象,该对象依次打开每个结果集并将结果写入您指定的表(或对结果集执行任何您想要的操作)。如果您喜欢疼痛,也可以在 DMO 中进行。

于 2008-11-06T19:37:21.500 回答
1

有两种方法可以轻松做到这一点。要么将结果粘贴到临时表中,然后从存储过程中引用临时表。另一种选择是将结果放入用作 OUTPUT 变量的 XML 变量中。

然而,这两种选择各有利弊。对于临时表,您需要将代码添加到创建调用过程的脚本中,以在修改过程之前创建临时表。此外,您应该在过程结束时清理临时表。

使用 XML,它可能会占用大量内存并且速度很慢。

于 2008-09-12T13:36:12.667 回答
0

您可以将它们选择到临时表中或编写表值函数以返回结果集。正在询问如何遍历结果集?

于 2008-09-12T13:31:51.117 回答