2010-03-18 6 views
32

Ich mache eine INSERT ... ON DUPLICATE KEY UPDATE, aber ich brauche den Updateteil bedingt, nur das Update, wenn einige zusätzliche Bedingung geändert hat.INSERT ... ON DUPLICATE KEY UPDATE mit WHERE?

Jedoch ist WHERE auf diesem UPDATE nicht erlaubt. Gibt es einen Workaround dafür?

Ich kann Kombinationen von INSERT/UPDATE/SELECT nicht tun, da dies über eine Replikation funktionieren muss.

Antwort

46

Ich empfehle Ihnen, IF() zu verwenden, um das zu tun.

Siehe: 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); 
+1

Ich wusste nie, dass ich auf den ursprünglichen Tabellenwert innerhalb des UPDATE-Teils zurückgreifen konnte. Dies löst wahrscheinlich mein Problem (obwohl meine alte Arbeit ziemlich gut ist :)) –

+1

Es kann passieren, dass MySQL sich beschweren wird 'Spalte in der Feldliste ist mehrdeutig' - dann müssten Sie verwenden: 'ON DUPLICATE KEY UPDATE daily_events.last_event_id = IF (daily_events.last_event_created_at boryn

+0

Der Link zu thewebfellas.com ist leider tot. –

3

Sie könnten zwei Insert-Anweisungen verwenden .. da Sie eine WHERE-Klausel zum SELECT-Teil für die Quelldaten hinzufügen können.

Wählen Sie zwei Datensätze aus, eine, die Sie mit "auf Duplikat" einfügen und die andere wird ohne "auf Duplikat" eingefügt.

10

Dies ist unsere endgültige Lösung, funktioniert wie ein Charme! Und nur eine Auswahl.

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()); 
Query OK, 1 row affected (0.01 sec) 

mysql> insert into test select id, "foo", now() from test where id = 4 and ts < now() on duplicate key update value = values(value), ts = values(ts); 
Query OK, 2 rows affected (0.00 sec) 
Records: 1 Duplicates: 1 Warnings: 0 
+1

Können Sie uns erklären, wie es funktioniert? – CMCDragonkai

+0

Die Erklärung ist in der Antwort von @lexu: zwei Anweisungen, die erste ist 'insert ignore', die zweite ist etwas wie' update ignore'. – xmedeko

+0

Sieht so aus, als würde die zweite Anweisung gerade 'update test set value =" foo ", ts = now() mit id = 4 und ts antak

0

Tabelle php_lock:
name: IdString, locked: Bool, time: Zeitstempel, locked_by: string
Werte einfügen oder Update
1, CURRENT_TIMESTAMP, ‚script '
wo name =' www 'UND 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`); 
-1

On duplicate key erlauben uns nicht, wo Klausel zu verwenden, so gibt es zwei alternative, das gleiche zu erreichen.

  1. Wenn Sie die meiste Zeit wissen, werden Sie den doppelten Schlüssel erhalten dann

    a. Update the table first using update query and where clause b. If update fails then insert the record into table using insert query

  2. Wenn Sie die meiste Zeit wissen Sie in Tabelle einzufügen gehen dann

    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

F oder Bezug von insert ignoreclick here

+1

Wie kann 'Einfügen ignorieren' fehlschlagen? –

+0

Wenn Sie versuchen, denselben eindeutigen Schlüssel einzufügen, wird der Befehl 'ignore ignorieren' fehlschlagen. –

+1

Nein, das ist was "ignorieren" tut. Es * ignoriert * die doppelte Schlüsselausnahme. –

-1
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), 
    last_event_created_at = IF(last_event_created_at < VALUES(last_event_created_at), VALUES(last_event_created_at), last_event_created_at); 
+0

Ist das nicht nur der Code aus der angenommenen Antwort? –