【问题标题】:Access to Result sets from within Stored procedures Transact-SQL SQL Server从存储过程 Transact-SQL SQL Server 中访问结果集
【发布时间】:2010-09-08 16:56:42
【问题描述】:

我使用的是 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 客户端使用的存储过程,它们返回多个结果集。这些不会更改为表值函数,实际上我根本无法更改程序。更改程序不是一种选择。

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

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

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

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

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

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

        【讨论】:

        • 我刚刚测试了 Brannon 的解决方案,实际上,如果调用的存储过程中的所有查询都返回相同数量的列和数据类型,则返回的结果集将由一个并集组成结果集。这几乎没用。感谢您的帮助。
        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

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

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

            第 1 步:开始编写存储过程,该存储过程将从多结果集存储过程中读取数据

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

            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));
            

            b.此时您可能需要声明一个游标来重复调用您将在此处创建的 CLR sproc:

            第 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") 连接。

            b.设置一个命令对象 (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。遍历每个表并将每一行插入到适当的临时表(您在上面的第一步中创建)。

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

            就是这样!

            ~肖恩,西雅图附近

            【讨论】:

            • 虽然 SQLCLR 是实际解决此问题的唯一方法,但转储到 DataSet 的简单途径是可扩展的,因为来自所有结果集的所有结果都将是在记忆中。更合适/可扩展的方法是遍历SqlDataReader 并返回从SqlDataReader 读取的每一行。 @DanRadu 在这里的回答,除了不处理所有数据类型(一个可修复的缺点)之外,还发送读取的每一行:stackoverflow.com/questions/6388489/…
            【解决方案7】:

            还有一个你也可以做的事情。将可选参数 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-31
              • 1970-01-01
              • 2012-01-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-11-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多