【问题标题】:Update statement works with temp table but not with table valued variables更新语句适用于临时表,但不适用于表值变量
【发布时间】:2017-05-22 18:58:57
【问题描述】:

我定义了这张表:

CREATE TABLE #stagingtable
(
    id int identity(1,1),
    typeflag int default 0,
    resourcetype varchar(25),
    resource varchar(40),
    est int,
    planned int,
    actual int
)

And then I am looking for places where the resourcetype is not the same as the resourcetype in the previous row, so I wrote the following UPDATE:

UPDATE #stagingtable
SET typeflag = 1 
WHERE id = (
    SELECT min(id)
    FROM #stagingtable
)
OR resourcetype <> (
    SELECT resourcetype
    FROM #stagingtable rt2
    WHERE rt2.id = (
        SELECT MAX(id) 
        FROM #stagingtable rt3
        WHERE rt3.id < #stagingtable.id
    )
)

这非常有效。但是,我所处的环境不允许我使用临时表(RDL!)。所以我把我的表改成了表值变量:

DECLARE @stagingtable TABLE
(
    id int identity(1,1),
    typeflag int default 0,
    resourcetype varchar(25),
    resource varchar(40),
    est int,
    planned int,
    actual int
)

But the following code doesn't work. 

UPDATE @stagingtable
SET typeflag = 1 
WHERE id = (
    SELECT min(id)
    FROM @stagingtable
)
OR resourcetype <> (
    SELECT resourcetype
    FROM @stagingtable rt2
    WHERE rt2.id = (
        SELECT MAX(id) 
        FROM @stagingtable rt3
        WHERE rt3.id < @stagingtable.id
    )
)

我收到消息:

Msg 137, Level 16, State 1, Line 431 必须声明标量变量 “@stagingtable”。

有没有办法更改更新语句以使其正常工作?

【问题讨论】:

  • @variables 是批次的本地变量。我假设您在某个地方有一个 GO 命令,或者正在其他可访问的地方运行它。您可以尝试@@variable,但如果您试图随时保留此变量,则不可行。为什么不直接使用#temp?

标签: sql sql-server tsql correlated-subquery rdl


【解决方案1】:

您的查询几乎没问题。您只需要在最后一行通过您给它的别名引用表变量:

WHERE rt3.id &lt; @stagingtable.id

DECLARE @stagingtable TABLE
(
    id int identity(1,1),
    typeflag int default 0,
    resourcetype varchar(25),
    resource varchar(40),
    est int,
    planned int,
    actual int
)


UPDATE @stagingtable
SET typeflag = 1 
WHERE id = (
    SELECT min(id)
    FROM @stagingtable
)
OR resourcetype <> (
    SELECT resourcetype
    FROM @stagingtable rt2
    WHERE rt2.id = (
        SELECT MAX(id) 
        FROM @stagingtable rt3
        WHERE rt3.id < rt2.id
    )
)

【讨论】:

  • 别名不错
  • 我认为这行不通,因为 rt2.id 与 stagingtable.id 不同
  • @GeoffSnowman 你在那里需要做什么?主表你不能像这样作为一个简单的变量访问,它仍然是一个表,你需要一个连接来从中获取行......
  • 在下面查看我的答案。
  • 我刚刚通过运行查询检查了这一点,而 rt3.id
【解决方案2】:

我设法想出了正确的语法,即在变量名周围添加方括号:

UPDATE @stagingtable
SET typeflag = 1 
WHERE id = (
    SELECT min(id)
    FROM @stagingtable
)
OR resourcetype <> (
    SELECT resourcetype
    FROM @stagingtable rt2
    WHERE rt2.id = (
        SELECT MAX(id) 
        FROM @stagingtable rt3
        WHERE rt3.id < [@stagingtable].id
    )
)

【讨论】:

  • 使用update ... from,这样您就可以为最外层的表设置别名。就像现在一样,很难读懂这篇文章并说出发生了什么,而且你以后会迷惑别人。 (stackoverflow.com/questions/4981481/…)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 2020-05-04
  • 2013-05-28
  • 2018-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多