【发布时间】:2011-01-28 23:50:39
【问题描述】:
我正在做一个INSERT ... ON DUPLICATE KEY UPDATE,但我需要更新部分是有条件的,只有在某些额外条件发生变化时才进行更新。
但是,WHERE 不允许用于此 UPDATE。有什么解决方法吗?
我不能进行 INSERT/UPDATE/SELECT 的组合,因为这需要在复制过程中起作用。
【问题讨论】:
标签: mysql replication
我正在做一个INSERT ... ON DUPLICATE KEY UPDATE,但我需要更新部分是有条件的,只有在某些额外条件发生变化时才进行更新。
但是,WHERE 不允许用于此 UPDATE。有什么解决方法吗?
我不能进行 INSERT/UPDATE/SELECT 的组合,因为这需要在复制过程中起作用。
【问题讨论】:
标签: mysql replication
我建议你使用 IF() 来做到这一点。
参考:conditional-duplicate-key-updates-with-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);
【讨论】:
ON DUPLICATE KEY UPDATE daily_events.last_event_id = IF(daily_events.last_event_created_at < VALUES(last_event_created_at), VALUES(last_event_id), daily_events.last_event_id);
这是我们的最终解决方案,就像一个魅力!
insert ignore 将确保主设备和从设备上都存在该行,以防它们被转移。
update ... where 确保只有全球范围内的最新更新才是所有复制完成后的最终结果。
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();
【讨论】:
insert ignore,第二个类似于update ignore。
update test set value = "foo", ts = now() where id = 4 and ts < now(),除了以非常复杂的方式。
insert ignore...,后跟update .... where ts < now()
您可以使用两个插入语句..因为您可以将 where 子句添加到源数据的选择部分。
选择两组数据,一组您将在“重复时”插入,另一组将在不“重复时”插入。
【讨论】:
ON DUPLICATE KEY UPDATE 的条件 WHERE 子句
IF() 函数的条件子句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 )
;
@doupdate 来标记 UPDATE 行是否满足条件。然后我们对 UPDATE 语句中使用的所有数据库列使用相同的变量【讨论】:
表
php_lock:name:idString,locked:bool,time:timestamp,locked_by:string
要插入的值或 更新
1, CURRENT_TIMESTAMP, 'script'
wherename='wwww' ANDlocked=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`);
【讨论】:
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 click here
【讨论】:
insert ignore 怎么会失败?
insert ignore 将失败。
ignore 所做的。它忽略重复键异常。