Позвольте мне изложить это, сказав, что то, что я описываю здесь, отлично работает в Mysql 5.6.x и ниже. Теперь мы пытаемся обновить mysql 5.7 и найти проблему с этим оператором UPDATE.
У нас есть таблица, которая выглядит так:
imagefile
----------
id int
itemId int
...
sequenceNumber int
updatedDate date
В нашем приложении пользователям необходимо изменить порядок изображений в элементе Item. Наш SQL для этого выглядит следующим образом:
UPDATE imageFile f1
JOIN (
SELECT f2.id, (@row:=@row+1) rowNum
FROM imageFile f2, (SELECT @row:=0) dm
WHERE f2.itemId = 8035323
ORDER BY f2.sequenceNumber, f2.updatedDate
) rs ON f1.id = rs.id
SET f1.sequenceNumber = rs.rowNum;
Если я запускаю только часть select в качестве автономного запроса, она производит следующее:
SELECT f2.id, f2.sequenceNumber, sqNum (@row:=@row+1) rowNum, updatedDate
FROM imageFile f2, (SELECT @row:=0) dm
WHERE f2.itemId = 8035323
ORDER BY f2.sequenceNumber, f2.updatedDate;
id sqNum rowNum updatedDate
| 9 | 1 | 1 |2018-04-16 18:39:12
| 8 | 2 | 2 |2018-04-16 18:38:42
| 7 | 3 | 3 |2018-04-16 18:37:03
| 6 | 4 | 4 |2018-04-16 18:37:28
| 5 | 5 | 5 |2018-04-16 18:36:37
| 4 | 6 | 6 |2018-04-16 18:38:16
| 3 | 7 | 7 |2017-09-12 16:59:20
Что правильно и точно, что я ожидаю... После запуска UPDATE с SELECT в качестве подзапроса/соединения я получаю следующее:
id sqNum rowNum updatedDate
| 3 | 1 | 1 |2017-09-12 16:59:20
| 4 | 2 | 2 |2018-04-16 18:38:16
| 5 | 3 | 3 |2018-04-16 18:36:37
| 6 | 4 | 4 |2018-04-16 18:37:28
| 7 | 5 | 5 |2018-04-16 18:37:03
| 8 | 6 | 6 |2018-04-16 18:38:42
| 9 | 7 | 7 |2018-04-16 18:39:12
Что совершенно неправильно и, похоже, не соответствует каким-либо приказом, о чем я сказал. Очевидно, что что-то изменилось в новой версии mysql. Когда я делаю EXPLAIN для этого запроса в каждой версии, он тоже отличается...
5.6.34
id select_type table type possible keys key key length ref rows extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 35 NULL
1 PRIMARY i1 eq_ref PRIMARY PRIMARY 4 rs.id 1 NULL
2 DERIVED <derived3> system NULL NULL NULL NULL 1 Using filesort
2 DERIVED i2 ref uc_ItemNumber, in_workspaceId uc_ItemNumber 4 const 35 Using where
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
5.7.18
id select_type table type possible_keys key key_len ref rows extra
1 PRIMARY <derived2> ALL 35
1 UPDATE i1 eq_ref PRIMARY PRIMARY 4 rs.id 1
2 DERIVED i2 ref uc_ItemNumber, in_workspaceId uc_ItemNumber 4 const 35 Using temporary; Using filesort
2 DERIVED <derived3> ALL 1 Using join buffer (Block Nested Loop)
3 DERIVED No tables used
Мой вопрос: как мне заставить это вернуться к предыдущему/желаемому поведению?
Я, кажется, помню, что переменные сеанса не должны использоваться/полагаться на операторы MySQL DML. Но хорошей новостью является то, что мы можем переписать ваш запрос без переменных сеанса:
UPDATE imageFile f1
INNER JOIN
(
SELECT
f2.id,
(SELECT COUNT(*)
FROM imageFile t
WHERE t.itemId = 8035323 AND
(t.sequenceNumber < f2.sequenceNumber OR
t.sequenceNumber = f2.sequenceNumber AND
(t.updatedDate < f2.updatedDate OR
(t.updatedDate = f2.updatedDate AND t.id < f2.id)))) rowNum
FROM imageFile f2
WHERE f2.itemId = 8035323
) rs
ON f1.id = rs.id
SET f1.sequenceNumber = rs.rowNum;