web-dev-qa-db-ja.com

INSERT ... ON WHEREを使用した重複キーの更新?

私はINSERT ... ON DUPLICATE KEY UPDATEしかし、更新部分が条件付きである必要があり、追加条件が変更された場合にのみ更新を行います。

ただし、WHEREはこのUPDATEでは許可されません。これに対する回避策はありますか?

INSERT/UPDATE/SELECTを組み合わせて実行することはできません。これは、レプリケーションを処理する必要があるためです。

40

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);
61
LouisXIV

これが最終的な解決策であり、魅力のように機能します!

insert ignoreは、マスターとスレーブが迂回した場合に備えて、マスターとスレーブの両方に行が存在することを確認します。

pdate ... 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();
12

ソースデータの選択部分にwhere句を追加できるため、2つのinsertステートメントを使用できます。

2つのデータセットを選択します。1つは「複製時に」挿入し、もう1つは「複製時に」挿入せずに挿入します。

3
lexu

概要

  • AWUpsertCondyは[〜#〜] before [〜#〜][〜#〜] after [ 〜#〜]

SimplifiedProblemIllustration

問題

  • MySQLが重複したプライマリキーを検出した場合、AWUpsertCondyは挿入クエリを失敗させたくない
  • MySQLは_ON DUPLICATE KEY UPDATE_の条件付きWHERE句をサポートしません

解決

  • MySQLはIF()関数で条件節をサポートします
  • ここでは、ユーザーIDが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 )
;

_

落とし穴

  • UPDATE行が条件を満たしているかどうかにフラグを立てるために、MySQL変数_@doupdate_を導入します。次に、UPDATEステートメントで使用するすべてのデータベース列に同じ変数を使用します
  • 最初の条件では、変数を宣言し、条件が適用されるかどうかを決定します。このアプローチは、WHERE句よりも間違いなく面倒です

こちらもご覧ください

0
dreftymac

テーブル php_lock
name:idString、locked:bool、time:timestamp、locked_by:ストリング
挿入または更新する値
1、CURRENT_TIMESTAMP、 'script'
where 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`);
0
Tito100