诀窍是如何获得MySQL中最后更新的行的ID'工作?

时间:2016-04-14 02:17:29

标签: php mysql

我试图选择最后更新的行'我的表的ID,然后我发现这个问题How to get ID of the last updated row in MySQL?

SET @uids := null;
UPDATE footable
   SET foo = 'bar'
 WHERE fooid > 5
   AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;

解决方案有效,但我不明白为什么我必须将@uids设置为null而不是空字符串。为什么此语句仅选择受影响的行而不是匹配的行,即使附加了限制子句也是如此。这是MySQL定义的行为吗?我会查看MySQL手册的哪一页?

mysql> select * from transaction_test;
+----+--------+------------+
| id | value1 | value2     |
+----+--------+------------+
|  1 |      1 | 1460600984 |
|  2 |      2 | 1460598960 |
+----+--------+------------+
2 rows in set (0.00 sec)

mysql>  set @ids=null;update  transaction_test set value2=unix_timestamp(now()) where 1=1 and  ( SELECT @ids:=concat_ws(',',@ids,value1)  ) limit 1;select @ids;
Query OK, 0 rows affected (0.00 sec)

Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

+------+
| @ids |
+------+
| 1    |
+------+
1 row in set (0.00 sec)

mysql>  set @ids='';update  transaction_test set value2=unix_timestamp(now()) where 1=1 and  ( SELECT @ids:=concat_ws(',',@ids,value1)  ) limit 1;select @ids;
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0

+------+
| @ids |
+------+
| ,1,2 |
+------+
1 row in set (0.00 sec)

1 个答案:

答案 0 :(得分:2)

如果您将@uids初始化为空字符串,那么CONCAT_WS(',', fooid, @uids)会在第一次连接时产生fooid,而不是fooid,因为它会连接fooid {1}}和''之间带逗号。但是当CONCAT_WS()的任何参数都是NULL时,它被完全忽略,并且它与相邻元素之间没有逗号。

它仅选择受影响的行,因为AND执行短路。这意味着从左到右评估参数,如果第一个参数是FALSE,它根本不评估第二个参数。因此,只有在@uids := ...fooid > 5时才会执行TRUE作业。

如果您有LIMIT子句,则行为取决于您排序的列是否已编入索引。如果是,它将按顺序扫描索引,然后评估WHERE子句,并在达到限制计数时停止,因此只有限制内的行才会包含在@uids中。或者,如果您没有ORDER BY子句,它只扫描表,直到达到限制。

但是,您无法可靠地依赖于此,这取决于查询优化器如何分析查询。

但是如果排序列未编入索引,或者查询优化器无法执行上述优化,则可能必须扫描整个表,选择与WHERE子句匹配的所有行进入临时表,然后对其执行排序。在这种情况下,@uids将包含所有匹配的ID,而不仅仅是限制内的ID。您可以使用子查询来解决此问题。

SET @uids := null;
UPDATE footable AS t1
JOIN (SELECT fooid
      FROM footable
      WHERE fooid > 5
      ORDER BY somecolumn
      LIMIT 10) AS t2
ON t1.fooid = t2.fooid
SET t1.foo = 'bar'
WHERE @uids := CONCAT_WS(',', fooid, @uids);
SELECT @uids;