2009-09-18 122 views
12
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是一个临时表。如何从存储过程返回临时表

任何想法???

+0

请重新格式化您的sql代码。 – 2009-09-18 10:22:22

+0

该代码不是有效的SQL。这可能是,如果“RETURN @WinNumbers”是“DECLARE @WinNumbers”,但其余部分看起来是正确的返回我现在看到的最终结果集 – 2009-09-18 10:35:37

+0

,我发布了错误的代码。有“DECLARE @WinNumbers”,但它仍然不起作用。 – dani 2009-09-18 10:46:49

回答

6

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

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

你可以找到一个例子here

+0

我正在使用sql server 2005 – dani 2009-09-18 10:43:07

25

这个代码看看,

CREATE PROCEDURE Test 

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

    insert @tab select eno,ename from emp 

    select * from @tab 
RETURN 
+0

这将如何返回/输出一个表变量给调用者?它目前返回一个结果集。 – 2009-09-18 10:53:43

+3

它返回select语句(实际问题)的结果,在这种情况下,恰好是本地表变量@tab的内容。 – JeffO 2009-09-18 13:56:54

+5

如果我执行'EXECUTE测试'我如何访问@tab? – whytheq 2012-08-07 15:41:05

0

过程的返回类型为int。

您也可以返回结果集(如你的代码目前确实)(好吧,你也可以发送邮件,这是字符串)

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

编辑:

(或作为另一个海报所说,你也可以使用一个表值函数,而不是一个过程)

2

一个临时表可以在调用者创建,然后从填充被称为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; 
0

是的你可以。

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

在这个存储过程的最后,你写的:

SELECT * FROM @tbRetour 

要执行存储过程,你写的:

USE [...] 
GO 

DECLARE @return_value int 

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

GO 
0

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

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

之前调用SP利用这个简单的选择创建临时表:

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

这具有以下独特的优势:

  • 的临时表是本地到当前会话,不像## ,因此不会与来自 不同会话的SP并发呼叫冲突。超出范围时它也会自动丢弃。
  • 模板表与SP保持一致,因此如果对输出进行的更改是 (例如添加了新列),则SP的预先存在的 呼叫者不会中断。来电者不需要改变。
  • 您可以定义任意数量的输出表,命名为 一个SP,并填充全部。您还可以定义具有不同命名的替代输出 ,并让SP检查临时表 的存在以查看哪些需要填充。
  • 同样,如果进行了重大更改但希望保持向后兼容性,则可以为后面的 版本创建一个新的模板表和命​​名,但仍然支持早期版本,方法是检查调用程序创建哪个表 表。