在表的每一行上执行更新

时间:2016-10-09 17:01:21

标签: mysql sql

我有以下SQL:

DROP TABLE IF EXISTS scores;

CREATE TABLE scores
  (
     id    INTEGER PRIMARY KEY,
     nom   VARCHAR(10),
     score INTEGER,
     rang  INTEGER
  );

INSERT INTO scores
VALUES      (1,'a',91,11),
            (2,'b',92,12),
            (3,'c',93,13),
            (4,'d',94,14);

UPDATE scores
SET    nom = 'foo',
       score = 1,
       rang = 0
WHERE  id = (SELECT id
             ORDER  BY score DESC
             LIMIT  1);

我想只更新得分最高的行(即94)但是当我执行请求时,表的每一行都采用这些值(demo)。

+----+-----+-------+------+
| id | nom | score | rang |
+----+-----+-------+------+
|  1 | foo |     1 |    0 |
|  2 | foo |     1 |    0 |
|  3 | foo |     1 |    0 |
|  4 | foo |     1 |    0 |
+----+-----+-------+------+

我不明白为什么?有人能帮帮我吗?

2 个答案:

答案 0 :(得分:1)

您可以在MySQL的order by中使用limitupdate。所以,我认为你的意思是:

UPDATE scores
    SET nom = 'foo', score = 1, rang = 0
    ORDER BY score DESC
    LIMIT 1;

答案 1 :(得分:1)

update scores SET nom='foo', score=1, rang=0 WHERE id= (SELECT id order by score DESC LIMIT 1)

想想这句话的内容。请记住,相等性检查限制了行集。每个更新语句都隐含地表示“更新与where子句匹配的每一行”。

首先看一下子查询。

(SELECT id order by score DESC LIMIT 1)

请注意该查询中没有FROM子句?如果没有FROM子句,相对于idscore列名称是什么?它们与外部陈述有关。 order by score DESC LIMIT 1具有误导性。他们工作,但他们没有做太多,因为你正在排序一个数字。

对每一行运行此WHERE子句:

WHERE id= (SELECT id order by score DESC LIMIT 1)

你在说什么,如果他的id列等于他的id列,则该行匹配。好吧,对于给定的行,给定列中的值总是等于它自己。

因此,您的整体更新谓词是匹配id等于其id的任何行,这自然会匹配每一行。

我认为你的意思是:

update scores
SET nom='foo', score=1, rang=0
WHERE id= (SELECT s.id from scores s order by s.score DESC LIMIT 1)

也就是说,在id表中找到最高scores,然后更新id等于特定id的任何行。它应该只匹配一行。

戈登指出,你也可以简化整个事情:

UPDATE scores
SET nom = 'foo', score = 1, rang = 0
ORDER BY score DESC
LIMIT 1;