从存储过程 Transact-SQL SQL Server 中访问结果集
-
09-06-2019 - |
题
我正在使用 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 客户端使用的存储过程,它返回多个结果集。这些不会更改为表值函数,事实上我根本无法更改程序。改变程序不是一个选择。
过程返回的结果集的数据类型或列数不同。
解决方案
简短的回答是:你做不到。
从 T-SQL 中,如果不按照其他人的建议更改存储过程,就无法访问嵌套存储过程调用的多个结果。
为了完整起见,如果过程返回单个结果,您可以使用以下语法将其插入临时表或表变量中:
INSERT INTO #Table (...columns...)
EXEC MySproc ...parameters...
您可以对返回多个结果的过程使用相同的语法,但它只会处理第一个结果,其余结果将被丢弃。
其他提示
通过创建一个包含内部数据集的 SQL2005 CLR 存储过程,我可以轻松地做到这一点。
您会看到,默认情况下,新的 SqlDataAdapter 会将多结果集存储过程填充到多表数据集中。这些表中的数据可以依次插入到您要编写的调用存储过程中的#Temp 表中。 数据集.ReadXmlSchema 将向您显示每个结果集的架构。
步骤1:开始写入将从多结果集存储过程中读取数据的存储过程
A。根据架构为每个结果集创建一个单独的表。
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 存储过程:
第2步:制作 CLR 存储过程
Partial Public Class StoredProcedures
<Microsoft.SqlServer.Server.SqlProcedure()> _
Public Shared Sub usp_SF_ReadSFIntoTables()
End Sub
End Class
A。连接使用 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.迭代每个表并将每一行插入相应的临时表(您在上面的第一步中创建的)。
最后说明:根据我的经验,您可能希望在表之间强制执行一些关系,以便您知道每个记录来自哪个批次。
这就是全部了!
~ 肖恩,西雅图附近
您也可以做一个拼凑的事情。将可选参数 N int 添加到您的存储过程中。默认 N 值为 -1。如果 N 的值为 -1,则执行每一项选择。否则,进行第 N 次选择,并且仅进行第 N 次选择。
例如,
if (N = -1 or N = 0)
select ...
if (N = -1 or N = 1)
select ...
未指定 N 的存储过程的调用者将获得包含多个表的结果集。如果您需要从另一个存储过程中提取一个或多个这些表,只需调用您的存储过程并指定 N 值即可。您必须为要提取的每个表调用一次存储过程。如果您需要结果集中的多个表,则效率较低,但它在纯 TSQL 中确实有效。
请注意,对于 INSERT INTO ... 有一个额外的、未记录的限制。执行声明:它不能嵌套。也就是说, EXEC 调用的存储过程(或它依次调用的任何存储过程)本身不能执行 INSERT INTO ...执行。似乎每个进程都有一个累积结果的暂存器,如果它们是嵌套的,那么当调用者打开它时,你会收到错误,然后被调用者尝试再次打开它。
Matthieu,您需要为每种“类型”的结果维护单独的临时表。此外,如果您多次执行相同的操作,则可能需要向该结果添加一列,以指示它是由哪个调用产生的。
遗憾的是这是不可能做到的。当然,问题是没有 SQL 语法允许这样做。当然,它发生在“幕后”,但您无法在 TSQL 中获得这些其他结果,只能通过 ODBC 或其他方式从应用程序中获得。
就像大多数事情一样,有一种解决方法。诀窍是使用 TSQL 中的 ole 自动化创建一个 ADODB 对象,该对象依次打开每个结果集并将结果写入您指定的表(或对结果集执行任何您想要的操作)。如果你喜欢痛苦,也可以在 DMO 中进行。
有两种方法可以轻松做到这一点。将结果粘贴到临时表中,然后从存储过程中引用临时表。另一种选择是将结果放入用作 OUTPUT 变量的 XML 变量中。
然而,这两种选择都各有利弊。对于临时表,您需要将代码添加到创建调用过程的脚本中,以在修改过程之前创建临时表。另外,您应该在过程结束时清理临时表。
对于 XML,它可能会占用大量内存并且速度很慢。
您可以将它们选择到临时表中或编写表值函数来返回结果集。正在询问如何迭代结果集?