如何从存储过程返回临时表

时间:2009-09-18 10:18:50

标签: sql-server stored-procedures temp-tables

CREATE PROCEDURE [test].[proc]
@ConfiguredContentId int,
@NumberOfGames int
AS
BEGIN
 SET NOCOUNT ON
 RETURN 
 @WunNumbers TABLE (WinNumb int)

    INSERT INTO @WunNumbers (WinNumb)
 SELECT TOP (@NumberOfGames) WinningNumber
 FROM [Game].[Game] g
 JOIN [Game].[RouletteResult] AS rr ON g.[Id] = rr.[gameId]
 WHERE g.[ConfiguredContentId] = @ConfiguredContentId
 ORDER BY g.[Stoptime] DESC

 SELECT WinNumb, COUNT (WinNumb) AS "Count"
 FROM @WunNumbers wn
 GROUP BY wn.[WinNumb]
END
GO

此存储过程从第一个select语句返回值,但我希望返回第二个select语句的值。表@WunNumbers是一个临时表。

任何想法???

6 个答案:

答案 0 :(得分:27)

看一下这段代码,

CREATE PROCEDURE Test

AS
    DECLARE @tab table (no int, name varchar(30))

    insert @tab  select eno,ename from emp  

    select * from @tab
RETURN

答案 1 :(得分:6)

您使用的是哪个版本的SQL Server?在SQL Server 2008中,您可以使用Table Parameters and Table Types

另一种方法是从用户定义的函数返回一个表变量,但我不是这种方法的忠实粉丝。

您可以找到示例here

答案 2 :(得分:3)

可以在调用者中创建临时表,然后从调用的SP填充。

  create table #GetValuesOutputTable(
     ...   
  );

  exec GetValues; -- populates #GetValuesOutputTable

  select * from #GetValuesOutputTable;

这种方法优于“insert exec”的一些优点是它可以嵌套,并且可以用作输入或输出。

一些缺点是“参数”不是公共的,表创建存在于每个调用者中,并且表的名称可能与其他临时对象冲突。当临时表名称与SP名称紧密匹配并遵循某些约定时,它会有所帮助。

更进一步,对于仅输出临时表,insert-exec方法和临时表方法可以由被调用SP同时支持。这对于链接SP没有多大帮助,因为表仍然需要在调用者中定义,但可以帮助简化cmd行的测试或在外部调用时。

  -- The "called" SP
  declare
      @returnAsSelect bit = 0;

  if object_id('tempdb..#GetValuesOutputTable') is null
  begin
      set @returnAsSelect = 1;
      create table #GetValuesOutputTable(
         ...   
      );
  end

  -- populate the table

  if @returnAsSelect = 1
      select * from #GetValuesOutputTable;

答案 3 :(得分:0)

过程的返回类型是int。

你也可以返回结果集(就像你的代码当前那样)(好吧,你也可以发送消息,这是字符串)

这些是你可以做的唯一“回报”。虽然您可以将表值参数添加到过程(请参阅BOL),但它们只是输入。

修改

(或者如另一张海报所提到的,你也可以使用表值函数,而不是程序)

答案 4 :(得分:0)

是的,你可以。

在存储过程中,填写表@tbRetour

在存储过程的最后,您写道:

SELECT * FROM @tbRetour 

要执行存储过程,请编写:

USE [...]
GO

DECLARE @return_value int

EXEC @return_value = [dbo].[getEnregistrementWithDetails]
@id_enregistrement_entete = '(guid)'

GO

答案 5 :(得分:0)

首先创建一个真实的永久表作为模板,该表具有返回的临时表所需的布局,使用命名约定将其标识为模板并将其符号链接到SP,例如 tmp_SPName_Output 。该表永远不会包含任何数据。

在SP中,使用INSERT按照相同的命名约定将数据加载到临时表中,例如: #SPName_Output ,假设存在。您可以测试它的存在,如果不存在则返回错误。

在调用sp之前,使用这个简单的select来创建临时表:

SELECT TOP(0) * INTO #SPName_Output FROM tmp_SPName_Output;
EXEC SPName;
-- Now process records in #SPName_Output;

这有以下明显优势:

  • 临时表是当前会话的本地,与##不同,因此不会与来自SP的并发调用冲突 不同的会议。超出范围时也会自动删除。
  • 模板表与SP一起维护,因此如果有更改 对输出(例如,添加了新列)然后预先存在 SP的来电者不会破坏。调用者不需要更改。
  • 您可以定义具有不同命名的任意数量的输出表 一个SP并填满所有。您还可以定义替代输出 用不同的命名并让SP检查temp的存在 表格,以查看哪些需要填写。
  • 同样,如果进行了重大更改,但您希望保持倒退 兼容性,您可以拥有一个新的模板表并为后面的命名 版本,但仍然通过检查哪个临时版支持早期版本 调用者创建的表。