2010-03-18 14 views
32

Estoy haciendo un INSERT ... ON DUPLICATE KEY UPDATE pero necesito que la parte de la actualización sea condicional, solo haciendo la actualización si alguna condición adicional ha cambiado.INSERTAR ... ¿ACTUALIZAR LLAVE DUPLICADA con DÓNDE?

Sin embargo, WHERE no está permitido en este UPDATE. ¿Hay alguna solución para esto?

No puedo hacer combinaciones de INSERT/UPDATE/SELECT, ya que esto tiene que funcionar en una replicación.

Respuesta

46

Le sugiero que utilice IF() para hacer eso.

Consulte: 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

Nunca supe que podría acceder al valor de la tabla original dentro de la parte UPDATE. Esto probablemente soluciona mi problema (aunque mi antiguo trabajo es bastante bueno :)) –

+1

Puede suceder que MySQL se queje de que 'la columna en la lista de campos es ambigua' - entonces necesitarías usar: 'EN ACTUALIZACIÓN DE LLAVE DUPLICADA daily_events.last_event_id = IF (daily_events.last_event_created_at boryn

+0

El enlace publicado en thewebfellas.com está muerto, por desgracia. –

3

puede usar dos instrucciones de inserción ... ya que PUEDE agregar una cláusula where a la parte de selección para los datos de origen.

seleccione dos juegos de datos, uno que se insertará con 'en duplicado' y el otro se insertará sin 'en duplicado'.

10

¡Esta es nuestra solución final, funciona como un encanto! Y solo uno seleccione.

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

Podría explicar cómo funciona? – CMCDragonkai

+0

La explicación está en la respuesta @lexu: dos declaraciones, la primera es 'insertar ignorar', la segunda es algo así como' actualizar ignorar'. – xmedeko

+0

Parece que la segunda instrucción solo está haciendo 'update test set value =" foo ", ts = now() donde id = 4 y ts antak

0

mesa php_lock:
name: idString, locked: bool, time: fecha y hora, locked_by: cadena
valores para insertar o actualización
1, CURRENT_TIMESTAMP, 'guión '
donde 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`); 
-1

On duplicate key no nos permiten usar cláusula where, por lo que hay dos alternativas para lograr el mismo.

  1. Si conoce la mayoría de las veces obtendrá la clave duplicada entonces

    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. Si conoce la mayor parte del tiempo que se va a insertar en la tabla a continuación

    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 o referencia de insert ignoreclick here

+1

¿Cómo puede 'insert ignore' fail? –

+0

si intenta insertar la misma clave única 'insert ignore' fallará. –

+1

No, eso es lo que 'ignore' hace. * Ignora * la excepción de clave duplicada. –

-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

¿No es este solo el código de la respuesta aceptada? –

Cuestiones relacionadas