2009-04-18 22 views
14

Muy a menudo, quiero ejecutar una consulta en uno de mis usuarios donde quiero una fila almacenada y asociada con ese usuario, en una relación de 1 a 1. Entonces, digamos (esto es solo un ejemplo arbitrario), que tengo una tabla que hace un seguimiento del auto de un usuario, junto con algo de información sobre el auto. Cada usuario puede tener 0 o 1 automóvil. Si el usuario no tiene automóvil, no hay ninguna entrada en la tabla para ese usuario. tablaMySQL "buena" manera de insertar una fila si no se encuentra, o actualizarla si se encuentra

coches (de nuevo, sólo un ejemplo): identificación, user_id, car_make, car_model

Así, cuando actualice esta tabla, siempre termino haciendo algo como esto (pseudo-código):

result = SELECT * FROM cars WHERE user_id=5 
if (num_rows(result)>0){ 
    UPDATE cars SET car_make='toyota', car_model='prius' WHERE user_id=5 
}else{ 
    INSERT INTO cars (user_id, car_make, car_model) VALUES (5, 'toyota', 'prius') 
} 

¿Cómo puedo convertir esto en una declaración elegante que funciona "atómicamente"? ¿Qué sucede si, en otro proceso, la fila se ELIMINA entre las instrucciones SELECT y UPDATE? Mi instrucción UPDATE fallará donde debería haberse ejecutado la instrucción INSERT. ¡Y siento que necesito hacer dos declaraciones similares (pero diferentes) para lograr lo mismo! Lo que necesito es una declaración que me asegure que los datos que deseo existen en la tabla, especialmente cuando solo quiero 1 fila que satisfaga mis requisitos. Por ejemplo, podría ser algo así como (esto es totalmente inventada por supuesto):

MAKE SURE A ROW IN cars WHERE user_id=5 IS SET WITH car_make='toyota', car_model='prius' 

esta manera, si user_id de 5 ya existe, se actualizará, de lo contrario, se insertará. Además, si he cambiado los requisitos, por ejemplo, decir que cada usuario puede tener cero o uno vagones de un car_make dado, entonces podría indicar, además, que:

MAKE SURE A ROW IN cars WHERE user_id=5 AND car_make='toyota' IS SET WITH car_model='prius' 

espero que mi pregunta tiene sentido! ¿Cómo puedo mejorar esta operación básica de inserción si no se encuentra o actualización si se encuentra tan a menudo? ¡Gracias por cualquier ayuda!

Respuesta

0

En Oracle tiene Merge.

No tengo idea en MySql, pero el término podría darte algo más para buscar.

2

Esto se denomina UPSERT (UP date o en SERT). Hay varias preguntas sobre SO que puede buscar. See Wikipedia

EDIT: MySQL 4.1+ apoya INSATE (INS ert o UPD ATE), que debe obtener la misma cosa, siempre y cuando usted tiene una clave principal. MySQL Manual

1

Creo que es más fácil cambiarlo. Intenta insertar, luego actualiza.

MySQL tiene específicamente una cláusula 'ON llave duplicada'

INSERT en los coches (campos) VALUES (valores) ON DUPLICATE KEY UPDATE ...

Por supuesto, esto requiere que tenga una configuración adecuada claves únicas .

0

un ejemplo de cómo he usado ON DUPLICATE KEY ACTUALIZACIÓN: INSERT INTO registro (nombre, valor) VALUES ('". $ Key."', '". $ Val."') ON DUPLICATE KEY UPDATE value = '" $ val.. "'"

5

de my other Stack Overflow answer:

Si usted quiere hacer esto en una sola instrucción, yo recomendaría el uso de la sintaxis INSERT ... ON DUPLICATE KEY UPDATE, de la siguiente manera:

INSERT INTO table (id, someothervalue) VALUES (1, 'hi mom') 
    ON DUPLICATE KEY UPDATE someothervalue = 'hi mom'; 

La declaración inicial INSERT será e xecute si no existe un registro con el valor de clave especificado (clave principal o único). Si ya existe un registro, se ejecuta la siguiente instrucción UPDATE (someothervalue = 3).

Esto es compatible con todas las versiones de MySQL. Para obtener más información, consulte el MySQL Reference Manual page for INSERT ... ON DUPLICATE KEY UPDATE

Cuestiones relacionadas