【问题标题】:How do I execute a sql statement through a variable (dynamic sql) that tries to do an insert into a variable table? [duplicate]如何通过尝试插入变量表的变量(动态 sql)执行 sql 语句? [复制]
【发布时间】:2012-09-11 05:09:37
【问题描述】:

可能重复:
How to use table variable in a dynamic sql statement?

如果我用 TEMPORARY TABLE 做我想做的事,它可以正常工作:

DECLARE @CTRFR VARCHAR(MAX)

SET @CTRFR = 'select blah blah blah' -- <-- very long select statement. this returns a 0 or some greater number. Please note! --> I NEED THIS NUMBER.

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo][#CTRFRResult]') AND type IN (N'U') ) 
   DROP TABLE [dbo].[#CTRFRResult]

CREATE TABLE #CTRFRResult
(
  CTRFRResult VARCHAR(MAX)
)

SET @CTRFR = 'insert into #CTRFRResult ' + @CTRFR
EXEC(@CTRFR)

以上工作正常。

问题是多个数据库使用同一个 TEMP 表。因此我需要使用 VARIABLE 表(而不是临时表)。

我下面的内容不起作用,因为它说必须声明表。

DECLARE @CTRFRResult TABLE
(
   CTRFRResult VARCHAR(MAX)
)

SET @CTRFR = 'insert into @CTRFRResult ' + @CTRFR -- I think the issue is here.
EXEC(@CTRFR)

@CTRFR 设置为insert into... 不起作用,因为我假设表名超出范围。我将如何使用变量表来模仿临时表代码?

我得到的错误信息是:

必须声明表变量“@CTRFRResult”

【问题讨论】:

    标签: tsql variables temp-tables


    【解决方案1】:

    你不能像这样使用带有动态 SQL 的 @ 表,你还必须在动态 sql 语句中创建表。

    但我认为您在使用 # 个表时完全没有问题。

    # 表将仅对当前会话可用 - 您可以有 100 个会话,每个会话都可以毫无问题地创建自己的版本。

    如果要创建其他会话可以访问的临时表,则需要改用##。

    【讨论】:

    • 问题是,多个会话创建相同的表名。我认为这是我一直遇到的问题。它正在创建对象 X,然后其他人运行另一个创建对象 X 的存储过程会导致问题,不是吗?
    • @Testifier,本地临时表(像#TableName 一样创建)没有这个问题,因为“数据库引擎通过在每个本地临时表名称内部附加一个数字后缀来做到这一点。”查看“本地临时表”部分on this page
    • @TimLehner,当我去删除这些临时表时,我如何知道一个临时表名称,其名称已被 SQL 更改?
    • @Testifier,SQL Server 会为您跟踪。只需在 SQL Server Management Studio 的两个窗口中创建相同的临时表即可。然后添加数据,然后查询它们,然后删除它们。它们始终不同,因为它们是在两个不同的会话中完成的。
    • @Testifier Tim 所说的是正确的,SQL Server 会为您管理这一切。查找 SQL 联机丛书以了解 # 个表和 ## 个表之间的差异。
    【解决方案2】:

    由于exec 在它自己的范围内运行,因此您不能像这样插入到表变量中。

    来自 Erland Sommarskog 的The Curse and Blessings of Dynamic SQL

    接下来要观察的是动态 SQL 不是存储过程的一部分,而是构成了它自己的作用域。调用动态 SQL 块类似于调用临时创建的无名存储过程。这会产生许多后果:

    在动态 SQL 块内,不能访问局部变量(包括表变量)或调用存储过程的参数。但是,如果您使用 sp_executesql,则可以将参数(输入和输出)传递给动态 SQL 块。

    【讨论】:

      【解决方案3】:

      虽然您无法将表变量作为参数发送到动态 sql 或其他存储过程,但您仍可以在特定情况下使用它。而不是

      SET @CTRFR = 'insert into @CTRFRResult ' + @CTRFR -- I think the issue is here.
      EXEC(@CTRFR)
      

      你可以说:

      insert into @CTRFRResult
        exec sp_executesql @CTRFR
      

      【讨论】:

        猜你喜欢
        • 2019-01-24
        • 2010-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-05
        • 1970-01-01
        相关资源
        最近更新 更多