如何将返回多个结果集的 SQL 存储过程中的单个结果集保存到临时表中?

发布于 2024-08-07 15:15:50 字数 1065 浏览 6 评论 0 原文

我需要将存储过程的结果集存储在临时表中(使用 SQL Server 2000)。从我读到的内容来看,这个(构造不良的示例)应该有效:

create table #tempTable (TempId int primary key, Column1 varchar(100), 
Column2 varchar(100), DateCreated datetime)

insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec sproc_Select_Stuff_By_DateCreated @Date1 = '1/1/2009', @Date2 = '1/2/2009'

但我得到: “插入错误:列名称或提供的值的数量与表定义不匹配。”

检查该过程(我无法编辑)揭示了这一点:

CREATE PROCEDURE sproc_Select_Stuff_By_DateCreated

@Date1 datetime,
@Date2 datetime
AS

BEGIN

SELECT TempId, Column1, Column2, DateCreated
FROM ReallyHugeMessOfJoinsAndCalculatedColumns
WHERE DateCreated between @Date1 and @Date2

SELECT @Date1 as Date1, @Date2 as Date2

END

所以它实际上回显了作为第二个结果集传递给它的参数。 (我不知道为什么;我认为任何调用该过程的东西都会知道它传入的数据。)

我的测试使我认为第二个结果集是导致插入失败的原因 - 就像 SQL 试图联合一样结果集在一起并失败。

我只需要将第一个结果集保存到临时表中。我怎样才能做到这一点?

编辑

感谢您指出 CLR 存储过程,但该功能是在 SQL 2005 中引入的 - 它不适用于 2000。(但我以前并不知道它们,它们看起来像它们)当我们升级时会很有用。)

因为唯一的其他答案看起来是“你不能” - 我想这对我来说又回到了绘图板。

I need to store the result set of a stored procedure in a temporary table (using SQL Server
2000). From what I've read, this (poorly constructed example) should work:

create table #tempTable (TempId int primary key, Column1 varchar(100), 
Column2 varchar(100), DateCreated datetime)

insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec sproc_Select_Stuff_By_DateCreated @Date1 = '1/1/2009', @Date2 = '1/2/2009'

But I get:
"Insert Error: Column name or number of supplied values does not match table definition."

Examining the procedure (which I cannot edit) reveals this:

CREATE PROCEDURE sproc_Select_Stuff_By_DateCreated

@Date1 datetime,
@Date2 datetime
AS

BEGIN

SELECT TempId, Column1, Column2, DateCreated
FROM ReallyHugeMessOfJoinsAndCalculatedColumns
WHERE DateCreated between @Date1 and @Date2

SELECT @Date1 as Date1, @Date2 as Date2

END

So it's actually echoing back the parameters passed into it as a second result set. (I have no idea why; I'd figure that anything calling the procedure would know what data it was passing in.)

My testing leads me to think that the second result set is what's causing the insert failure - like SQL is trying to union the result sets together and failing.

I only need the first result set saved to my temporary table. How can I do that?

Edit

Thanks for pointing out CLR stored proecedures, but that feature was introduced in SQL 2005 - it won't work for 2000. (But I wasn't previously aware of them, and they look like they'll be useful when we upgrade.)

As the only other answers look to be "you can't" - I guess it's back to the drawing board for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

画▽骨i 2024-08-14 15:15:50

由于您无法更改存储过程,因此您只有两个选择:

  • 使用可以捕获两个结果集的 CLR,并仅返回您想要的结果集。
  • 在您自己的过程或视图中复制您需要的查询。这是一个真正的 hack,并且 CLR 是首选。但是,您没有太多选择。

since you can't change the stored procedure, you have only two options:

  • use a CLR, that can capture both result sets, and return only the one you want.
  • duplicate the query you need in your own procedure or view. It is a real hack, and the CLR is preferred. However, you don't have many choices.
圈圈圆圆圈圈 2024-08-14 15:15:50

一般来说,在普通 SQL 中这是不可能的。 Brannon 的链接提供了使用 CLR 的可能解决方法。

另一方面,如果可以选择重构,请考虑在其自己的存储过程中使第一个查询原子化。然后可以从现有存储过程和任何其他代码调用它。您的代码仍然只在一处,没有任何损坏,并且您可以从纯 SQL 中获得更容易使用的东西。根据其功能,SP 的第一部分甚至可能是内联表值函数的良好候选者(我发现它们性能良好且灵活)。然后,您甚至不需要将输出捕获到临时表中,以将其用作执行其他处理的表(尽管如果您想多次使用它,您可能需要这样做)!

Generally, in plain SQL this is not possible. Brannon's link gives a possible workaround using the CLR.

On the other hand, if re-factoring is an option, think about making the first query atomic in it's own stored procedure. Then it can be called from both the existing stored procedure and any other code. Your code is still only in one place, nothing is broken, and you get something which can be more easily used from pure SQL. Depending on its function, the first part of the SP might even be a good candidate for an inline table-valued function (I've found these to be well-performant and flexible). Then you don't even need to capture the output into a temp table to use it as a table in doing other processing (although you might want to if you want to use it several times)!

撑一把青伞 2024-08-14 15:15:50

下面是一个完整的、有效的(针对 SQL 2005)示例。

坏消息是,我不相信有任何方法可以做你想做的事。对不起。看来SP作者让它不可能了。

如果有人想出一些创造性的方法来完成这项工作,那就太好了!

IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
    DROP TABLE #tempTable
GO
IF EXISTS (SELECT * FROM sys.procedures WHERE name = 'sproc_Select_Stuff_By_DateCreated')
    DROP PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
GO
CREATE PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
    @Date1 datetime,
    @Date2 datetime
AS BEGIN
    ;WITH t AS (
        SELECT
            1                       AS TempId,
            'Column1-val1'          AS Column1,
            'Column2-val1'          AS Column2,
            '2009-01-01 10:00:00'   AS DateCreated
        UNION ALL
        SELECT
            2,
            'Column1-val2',
            'Column2-val2',
            '2009-01-01 11:00:00'
    )
    SELECT
        TempId,
        Column1,
        Column2,
        DateCreated
    FROM t -- ReallyHugeMessOfJoinsAndCalculatedColumns
    WHERE DateCreated between @Date1 and @Date2

    SELECT @Date1 as Date1, @Date2 as Date2
END
GO

create table #tempTable (
    TempId int primary key,
    Column1 varchar(100),
    Column2 varchar(100),
    DateCreated datetime
)

insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec dbo.sproc_Select_Stuff_By_DateCreated
    @Date1 = '1/1/2009',
    @Date2 = '1/2/2009'

--SELECT * FROM #tempTable

----------------------------------------

Msg 213, Level 16, State 7, Procedure sproc_Select_Stuff_By_DateCreated, Line 26
Insert Error: Column name or number of supplied values does not match table definition.

Below is a complete, working (for SQL 2005) example of what you're talking about.

The bad news is, I don't believe there is any way to do what you're trying to do. Sorry. It looks like the SP writer made it impossible.

If someone comes up with some creative way to make this work, great!

IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
    DROP TABLE #tempTable
GO
IF EXISTS (SELECT * FROM sys.procedures WHERE name = 'sproc_Select_Stuff_By_DateCreated')
    DROP PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
GO
CREATE PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
    @Date1 datetime,
    @Date2 datetime
AS BEGIN
    ;WITH t AS (
        SELECT
            1                       AS TempId,
            'Column1-val1'          AS Column1,
            'Column2-val1'          AS Column2,
            '2009-01-01 10:00:00'   AS DateCreated
        UNION ALL
        SELECT
            2,
            'Column1-val2',
            'Column2-val2',
            '2009-01-01 11:00:00'
    )
    SELECT
        TempId,
        Column1,
        Column2,
        DateCreated
    FROM t -- ReallyHugeMessOfJoinsAndCalculatedColumns
    WHERE DateCreated between @Date1 and @Date2

    SELECT @Date1 as Date1, @Date2 as Date2
END
GO

create table #tempTable (
    TempId int primary key,
    Column1 varchar(100),
    Column2 varchar(100),
    DateCreated datetime
)

insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec dbo.sproc_Select_Stuff_By_DateCreated
    @Date1 = '1/1/2009',
    @Date2 = '1/2/2009'

--SELECT * FROM #tempTable

----------------------------------------

Msg 213, Level 16, State 7, Procedure sproc_Select_Stuff_By_DateCreated, Line 26
Insert Error: Column name or number of supplied values does not match table definition.
眉目亦如画i 2024-08-14 15:15:50

来自 Microsoft T-SQL 参考

INSERT EmployeeSales 
EXECUTE uspGetEmployeeSales;
GO

From the Microsoft T-SQL reference

INSERT EmployeeSales 
EXECUTE uspGetEmployeeSales;
GO
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文