INSERT, ON DUPLICATE KEY UPDATE и LAST_INSERT_ID()

261
14 января 2017, 12:17

Согласно ответам к вопросу на en.so пришёл к выводу, что обозначенные там инструменты - это то, что требуется в моей задаче, а именно: получить идентификатор "вставленной" строки, даже если этого по факту и не произошло.

INSERT INTO `table` (`id`, `text`) VALUES (1, 'tra-ta-ta')
 ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id`);

... при этом колонка id - PRIMARY KEY и AUTO_INCREMENT, а колонка text - UNIQUE.

Но исходя из этого кода получается, что id будет заменён (знак присваивания, как бы, на это намекает):

`id` = LAST_INSERT_ID(`id`)

Означает ли это, что значение идентификатора в соответствующей колонке действительно будет заменено (пусть и на тоже самое значение) с соответствующими последствиями, как то, например, срабатывание ON UPDATE CASCADE для FOREIGN KEY у какой-нибудь подключенной таблицы? А может и ON DELETE CASCADE сработает, как в случае, если использовать REPLACE вместо INSERT? Тогда совсем беда.

Прав ли я в своих сомнениях, и если это действительно так, то каким образом возможно решить проблему?

Answer 1
mysql> create table `table` (id serial, `text` varchar(16) unique);
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO `table` (`id`, `text`) VALUES (1, 'tra-ta-ta')
    ->  ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id`);
Query OK, 1 row affected (0.00 sec)
mysql> select * from `table`;
+----+-----------+
| id | text      |
+----+-----------+
|  1 | tra-ta-ta |
+----+-----------+
1 row in set (0.00 sec)
mysql> INSERT INTO `table` (`id`, `text`) VALUES (2, 'tro-lo-lo')
    ->  ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id`);
Query OK, 1 row affected (0.00 sec)
mysql>  select * from `table`;
+----+-----------+
| id | text      |
+----+-----------+
|  1 | tra-ta-ta |
|  2 | tro-lo-lo |
+----+-----------+
2 rows in set (0.00 sec)
mysql> INSERT INTO `table` (`id`, `text`) VALUES (3, 'tra-ta-ta')
    ->  ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id`);
Query OK, 0 rows affected (0.00 sec)
mysql> select LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+
1 row in set (0.00 sec)
mysql> select * from `table`;
+----+-----------+
| id | text      |
+----+-----------+
|  1 | tra-ta-ta |
|  2 | tro-lo-lo |
+----+-----------+
2 rows in set (0.00 sec)

Как мы видим, в третьем запросе на пополнение/изменение

Query OK, 0 rows affected (0.00 sec)

Да, у MySQL есть такая особенность - он считает обновлением только фактическое обновление. Т.е. связанное с тем, что итоговые данные не равны исходным.

UPD: Где-то накосячил. Чую, но сообразить не могу, слишком вечер. Завтра раскопаю всё и отпишусь.

READ ALSO
Подключиться к серверу особым способом

Подключиться к серверу особым способом

Я умею делать запросы на сервер GET/POSTА вот, если мне надо постоянно получать данные, то как быть? Неужели, такие же запросы, но в бесконечном...

305
Как скрыть Float Action Button при скролле ListView

Как скрыть Float Action Button при скролле ListView

Пробовал с CoordinatorLayout как в этом туториале но не сработалоМне кажется это из за того что у меня ListView находится внутри SwipyRefreshLayout

443