在查询字符串中引用表变量

时间:2013-11-11 15:11:25

标签: sql sql-server tsql

我已经创建了一个temprary表变量,然后我需要进行调整:

Declare @TempTable TABLE(
Name varchar(150),
CloseDate Date, 
Revenue Float)

.... <add data to it> .....    

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(CloseDate) 
            FROM @TempTable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT  Name, ' + @cols + ' from 
                (select 
                    t.Name,
                    t.CloseDate,
                    t.Revenue
                from @TempTable as t
                ) x
            pivot 
                (SUM(Revenue)
                    for CloseDate in (' + @cols + ')
                ) p '

execute(@query)

但是,我收到此错误:

Must declare the scalar variable "@TempTable".

当我使用普通的SELECT测试@TempTable变量时,它工作正常:

SELECT * from @TempTable

如何在查询字符串中成功引用变量?

1 个答案:

答案 0 :(得分:5)

不幸的是,当您使用execute和sp_executesql时,它们在自己的上下文中运行,因此它们无法引用在动态SQL范围之外定义的表变量对象。

在这种情况下,我倾向于创建临时表,并在tempdb中创建的临时表的名称中嵌入GUID。这确保了表名对于同时操作是唯一的,然后我将该guid放在创建的动态SQL中。

性能方面它稍慢但仍然很快,但是否对你来说是一个问题取决于它执行的次数和频率。

在对此答案的评论中与Damien进行了一些讨论之后,我们确定在执行动态SQL时可以使用本地临时表(单个标签)。

因此,如果将declare table变量更改为CREATE TABLE #TempTable并更改动态SQL中的引用,则此方法应该适合您。

我唯一担心的是使用临时表是对象的持久性,如果你的调用代码使用某种形式的连接池,这听起来就像在这里一样。

然而,作为一般的自我偏执的自我实践,我喜欢在创建表之前和语句末尾抛出其中一个以清理对象。

IF OBJECT_ID(N'tempdb..#TempTable') IS NOT NULL
DROP TABLE #TempTable

CREATE TABLE #TempTable (Value VARCHAR(50));