SQL :具有动态列值分配的更新语句
Posted
技术标签:
【中文标题】SQL :具有动态列值分配的更新语句【英文标题】:SQL : update statement with dynamic column value assignment 【发布时间】:2009-02-17 12:01:04 【问题描述】:想象一下下面的 sql 查询:
UPDATE MYTABLE
SET COL2 = (SELECT COL2 + 1 FROM (SELECT MAX(COL2) FROM MYTABLE) AS X)
WHERE ID IN (1,2,3,4,5)
假设在执行更新之前 MAX(COL2) 为 1。
我的意图是,对于 ID=1 的更新,COL2 被更新为“max(COL2) + 1”(即 2),而对于后续更新,“MAX(COL2) + 1”被重新评估,所以对于 ID=2、COL2=3 和 ID=3、COL2=4 等...
实际发生的是,对于所有行 (ID=1,2,3,4,5),COL2 的值为 2。
是否有一种聪明的方法可以在每次更新时“重新评估”MAX(COL2) +1 的值?我意识到这样做可能会出现性能问题,但我仍然很好奇!有没有更好的选择(不涉及多个更新语句)?
顺便说一句:如果您想知道上述查询(嵌套内表)使用的语法,请参见此处:SQL : Using the target table in an UPDATE statement in a nested FROM clause
【问题讨论】:
请发布您现在在表格中的内容以及您希望看到的结果。 【参考方案1】:UPDATE mytable, (
SELECT @loop := MAX(col1)
FROM
mytable
) o
SET col1 = (@loop := @loop + 1)
你在这里遇到的叫query stability
。
没有查询可以看到自己所做的更改,或者下面的查询:
UPDATE mytable
SET col1 = col2 + 1
WHERE col1 > col2
永远不会结束。
【讨论】:
【参考方案2】:这是我的做法:
SELECT MAX(col2) FROM mytable INTO @max;
UPDATE mytable
SET col2 = @max:=@max+1
WHERE id IN (1,2,3,4,5)
ORDER BY id;
我在 mysql 5.1.30 上对此进行了测试,它可以工作。
我首先设置了@max
变量,只是因为我发现@Quassnoi 在笛卡尔积中的技巧是不必要的且可读性较差。
请注意,MySQL 在UPDATE
语句中支持ORDER BY
(这不是标准SQL),您应该这样做,以确保按您想要的顺序更新值。否则 MySQL 不保证特定顺序。
【讨论】:
这也有效!但由于我通过 jdbc 将查询作为单个语句执行,因此我将使用 @Quassnoi's。【参考方案3】:declare @loop int
select @loop = 1
UPDATE MYTABLE
SET COL1 = @loop,
@loop = @loop+1
WHERE ID IN (1,2,3,4,5)
【讨论】:
【参考方案4】:是否有一种聪明的方法可以在每次插入时“重新评估”MAX(COL1) +1 的值?
除非您逐一更新行:(
这适用于 MSSQL,不知道 MySQL,但可能会给你一个想法:
DECLARE @Counter int
SELECT @Counter = MAX(COL2) FROM MYTABLE
UPDATE MYTABLE
SET @Counter = @Counter + 1,
COL1 = @Counter
WHERE ID IN (1,2,3,4,5)
编辑:我认为 SET 语句可以在 MSSQL 中简化为:
SET @Counter = COL1 = @Counter + 1
【讨论】:
【参考方案5】:应该在每次插入时重新评估它;大概 COL2 的最大值没有变化。确定不想选择 MAX(COL1)?
再次阅读您的问题,您混淆了插入和更新(现已修复)这两个术语,我被抛出了一个循环。
您正在尝试一次更新多条记录,但让它表现得好像在单独更新每条记录一样。这不会按您的预期工作。
您可以创建一个存储过程来循环遍历每个记录 WHERE ID IN (1,2,3,4,5) 并单独更新。或者,既然您只做 5 行,为什么不直接复制并粘贴该语句五次并将 WHERE 子句更改为 WHERE ID = 1
(以及后续行中的 2、3、4、5)。
【讨论】:
“除非你的 SQL 品牌不喜欢它?”我相信 MySQL 必须对 UPDATE 中的嵌套 SELECT 进行双重包装。我认为您的解决方案将为更新中的所有 5 行分配相同的 MAX(COL2) 值 显然是这样,假设原始帖子中的“BTW”链接是正确的。 @lc :回答“作为旁注,您为什么要将 MAX(COL2) 投射到临时表并再次从中选择?”请阅读全文(包括最后的 BTW) 是的,我明白了。请注意“显然如此”和我的编辑。很抱歉错过了第一次(和第二次)。以上是关于SQL :具有动态列值分配的更新语句的主要内容,如果未能解决你的问题,请参考以下文章