3

想象一下下面的 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:在嵌套 FROM 子句中的 UPDATE 语句中使用目标表

4

5 回答 5

11
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 

永远不会结束。

于 2009-02-17T12:14:52.840 回答
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 支持ORDER BYUPDATE语句中(这不是标准 SQL),您应该这样做,以确保按照您想要的顺序更新值。否则 MySQL 保证没有特定的顺序。

于 2009-02-17T14:34:23.053 回答
0
declare @loop int
select @loop = 1

UPDATE MYTABLE
SET COL1 = @loop,
    @loop = @loop+1
WHERE ID IN (1,2,3,4,5)
于 2009-02-17T12:07:31.190 回答
0

是否有一种聪明的方法可以在每次插入时“重新评估” 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
于 2009-02-17T12:10:07.533 回答
-1

它应该在每次插入时重新评估它;大概 COL2 的最大值没有变化。您确定不想选择 MAX(COL 1 )? 再次阅读您的问题,您混淆了插入和更新术语(现在已修复),我被抛出一个循环。


您正在尝试一次更新许多记录,但让它表现得好像它正在单独更新每个记录一样。这不会像你想要的那样工作。

您可以创建一个存储过程来循环遍历每个记录 WHERE ID IN (1,2,3,4,5) 并单独更新。或者,既然您只做 5 行,为什么不直接复制并粘贴该语句五次并将 WHERE 子句更改为WHERE ID = 1(以及后续行中的 2、3、4、5)。

于 2009-02-17T12:05:08.933 回答