INSERT... НА ОБНОВЛЕНИИ КЛЮЧА DUPLICATE с ГДЕ?
Я делаю INSERT ... ON DUPLICATE KEY UPDATE
, но мне нужно, чтобы часть обновления была условной, и только обновление, если какое-то дополнительное условие изменилось.
Однако WHERE
не допускается на этом UPDATE
. Есть ли обходной путь для этого?
Я не могу делать комбинации INSERT/UPDATE/SELECT, так как это необходимо для работы над репликацией.
Ответы
Ответ 1
Я предлагаю вам использовать IF() для этого.
См.: условный-дубликат-ключ-обновления-с-MySQL
INSERT INTO daily_events (created_on, last_event_id, last_event_created_at)
VALUES ('2010-01-19', 23, '2010-01-19 10:23:11')
ON DUPLICATE KEY UPDATE
last_event_id = IF(last_event_created_at < VALUES(last_event_created_at), VALUES(last_event_id), last_event_id);
Ответ 2
Это наше окончательное решение, работает как шарм!
Игнорирование вставки гарантирует, что строка существует как на главном, так и на ведомом устройстве, в случае, если они когда-либо были перенаправлены.
Обновление... где гарантирует, что только самое последнее обновление в глобальном масштабе является конечным результатом после выполнения всей репликации.
mysql> desc test;
+-------+--------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+-------------------+-------+
| id | int(11) | NO | PRI | NULL | |
| value | varchar(255) | YES | | NULL | |
| ts | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+--------------+------+-----+-------------------+-------+
mysql> insert ignore into test values (4, "foo", now());
mysql> update test set value = "foo", ts = now() where id = 4 and ts <= now();
Ответ 3
вы можете использовать два оператора вставки: поскольку вы можете добавить предложение where к части выбора для исходных данных.
выберите два набора данных, один из которых вы будете вставлять с символом "on duplicate", а другой будет вставлен без дубликата.
Ответ 4
table php_lock
:
name
: idString, locked
: bool, time
: метка времени, locked_by
: строка и значения для вставки или update
1, CURRENT_TIMESTAMP, 'script' где name
= 'wwww' AND locked
= 2
INSERT INTO `php_lock` (`name`, locked, `time`, `locked_by`)
(SELECT * FROM
(SELECT `name`,1,CURRENT_TIMESTAMP, 'script' FROM `php_lock`
WHERE `name`='wwww' AND `locked`=2
UNION (
SELECT 'wwww',1 ,CURRENT_TIMESTAMP, 'script')
) AS temp LIMIT 1)
ON DUPLICATE KEY UPDATE locked=VALUES(locked), `time`=VALUES(`time`), `locked_by`=VALUES(`locked_by`);
Ответ 5
обзор
- AWUpsertCondy хочет изменить ПЕРЕД на ПОСЛЕ
![SimplifiedProblemIllustration]()
проблема
- AWUpsertCondy не хочет, чтобы запрос вставки не выполнялся, если MySQL обнаруживает повторяющийся первичный ключ
- MySQL не поддерживает условное предложение WHERE с
ON DUPLICATE KEY UPDATE
Решение
- MySQL поддерживает условное предложение с помощью функции
IF()
- Здесь у нас есть простое условное обновление только тех элементов с идентификатором пользователя менее 9
INSERT INTO zzdemo_table02
(lname,userid)
SELECT
lname,userid
FROM(
SELECT
lname,userid
FROM
zzdemo_table01
) as tt01
ON DUPLICATE KEY UPDATE
userid=IF(@doupdate:=IF( (tt01.userid < 9) , True, False),
tt01.userid, zzdemo_table02.userid)
,lname=IF(@doupdate, tt01.lname , zzdemo_table02.lname )
;
Ловушки
- Мы вводим переменную MySQL
@doupdate
, чтобы указать, соответствует ли строка UPDATE условию. Затем мы используем эту же переменную для всех столбцов базы данных, которые мы используем в инструкции UPDATE. - В первом условном выражении мы оба объявляем переменную и определяем, применимо ли условное условие. Этот подход, возможно, более громоздкий, чем предложение WHERE
Смотрите также
Ответ 6
On duplicate key
не позволяют нам использовать предложение where, поэтому есть две альтернативы для достижения того же.
-
Если вы знаете, что большую часть времени вы получите дубликат, тогда
a. Update the table first using update query and where clause
b. If update fails then insert the record into table using insert query
-
Если вы знаете, что большую часть времени вы собираетесь вставлять в таблицу,
a. Insert the record into table using insert ignore query - what it does is actually ignore the insert if duplicate key found
b. If insert ignore fails then update the record using update query
Для справки insert ignore
нажмите здесь