2009-05-27 13 views
79

estoy teniendo un tiempo difícil la formación de una INSERT condicionalMySQL condicional Insertar

I tienen x_table con columnas (ejemplo, usuario, artículo) donde ID de instancia es única. Quiero insertar una nueva fila solo si el usuario ya no tiene un elemento determinado.

Por ejemplo intentar insertar ejemplo = 919191 user = 123 item = 456

Insert into x_table (instance, user, item) values (919191, 123, 456) 
    ONLY IF there are no rows where user=123 and item=456 

Cualquier ayuda u orientación en la dirección correcta sería muy apreciada.

Respuesta

90

Si el DBMS no impone limitaciones a qué tabla se seleccionan en cuando se ejecuta una inserción, Proveedores:

INSERT INTO x_table(instance, user, item) 
    SELECT 919191, 123, 456 
     FROM dual 
     WHERE NOT EXISTS (SELECT * FROM x_table 
          WHERE user = 123 
           AND item = 456) 

En esto, dual es una tabla con una sola fila (Originalmente se encuentra en Oracle, ahora en otro lugar también). La lógica es que la instrucción SELECT genera una única fila de datos con los valores requeridos, pero solo cuando los valores no se encuentran ya.

O bien, mire la instrucción MERGE.

+1

¿Es necesario crear 'dual' de antemano en este caso o se trata de algún tipo de tabla especial" temporal "creada por la consulta para el uso de la consulta solo? – itsmequinn

+8

Si aún no tiene 'dual', necesita crearlo. 'CREATE TABLE dual ( dummy CHAR (1) DEFAULT 'x' NOT NULL CHECK (dummy = 'x') PRIMARY KEY ); INSERT INTO dual VALUES ('x'); REVOKE ALL ON dual FROM PUBLIC; GRANT SELECT ON dual to PUBLIC; ' –

+0

Gracias es increíble saber – itsmequinn

0
Insert into x_table (instance, user, item) values (919191, 123, 456) 
    where ((select count(*) from x_table where user=123 and item=456) = 0); 

La sintaxis puede variar en función de su base de datos ...

+2

¿Para qué sirve esto? MySQL? – Neutralizer

+2

No pude hacer que esto funcione en MySQL. – hlin117

1

Si se agrega una restricción que (x_table.user, x_table.item) es único, a continuación, insertar otra fila con el mismo usuario y el punto fallará.

por ejemplo:

mysql> create table x_table (instance integer primary key auto_increment, user integer, item integer, unique (user, item)); 
Query OK, 0 rows affected (0.00 sec) 

mysql> insert into x_table (user, item) values (1,2),(3,4); 
Query OK, 2 rows affected (0.00 sec) 
Records: 2 Duplicates: 0 Warnings: 0 

mysql> insert into x_table (user, item) values (1,6); 
Query OK, 1 row affected (0.00 sec) 

mysql> insert into x_table (user, item) values (1,2); 
ERROR 1062 (23000): Duplicate entry '1-2' for key 2 
+0

Eso no está bien. Puede haber varias filas con el mismo usuario, pero no múltiples filas con un par de elementos de usuario. –

+0

Sí, sí. Lo leí mal Editado para hacer la restricción en el par. – NickZoic

+0

Buen comentario ... ejecuto la consulta en PHP usando mysql_query ("INSERT") y dejo la parte o muere, por lo tanto, dosent me advierte sobre el error, así que no tengo que hacer ningún control –

1

A pesar de que es bueno para comprobar si la duplicación antes de introducir sus datos Sugiero que se pone una restricción única/índice en las columnas de modo que no hay datos duplicados se pueden insertar por error.

10

Con un UNIQUE(user, item), hacer:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
    ON DUPLICATE KEY UPDATE user=123 

el bit user=123 es un "no-op" para que coincida con la sintaxis de la cláusula ON DUPLICATE sin hacer nada cuando hay duplicados.

+1

No puedo configurar un Único (usuario, artículo) porque puede haber instancias cuando hay varias instancias con el mismo usuario y artículo ... simplemente no cuando estoy haciendo esta inserción. –

0

Ligera modificación de la respuesta de Alex, usted podría también acaba de hacer referencia al valor de la columna existente:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
    ON DUPLICATE KEY UPDATE user=user 
21

¿Alguna vez ha intentado algo así?

INSERT INTO x_table 
SELECT 919191 as instance, 123 as user, 456 as item 
FROM x_table 
WHERE (user=123 and item=456) 
HAVING COUNT(*) = 0; 
+0

¡oh sí!solución inteligente y agradable con solo una declaración SELECT –

+0

Agradable. Esto funciona para postgresql en el primer intento, donde la respuesta aceptada no me pareció adecuada. – mightypile

39

También puede utilizar INSERT IGNORE, que silenciosamente ignora la inserción en lugar de actualizar o insertar una fila cuando se tiene un índice único en (usuario, artículo).

La consulta se verá así:

INSERT IGNORE INTO x_table(instance, user, item) VALUES (919191, 123, 456) 

Puedes añadir el índice único con CREATE UNIQUE INDEX user_item ON x_table (user, item).

+1

thx mucho ... simple y fácil y funcionó como un encanto – Zorox

+0

Según la documentación de MySQL INSERT IGNORE es la contraparte para REEMPLAZAR ... INSERTAR IGNORAR: mantener las filas anteriores. REEMPLAZAR: mantener nuevas filas. Ambos funcionan con llaves únicas. –

0

Así que éste representa PostgreSQL

INSERT INTO x_table 
SELECT NewRow.* 
FROM (SELECT 919191 as instance, 123 as user, 456 as item) AS NewRow 
LEFT JOIN x_table 
ON x_table.user = NewRow.user AND x_table.item = NewRow.item 
WHERE x_table.instance IS NULL 
2

En caso de que no desea establecer una restricción única, esto funciona como un encanto:

INSERT INTO `table` (`column1`, `column2`) SELECT 'value1', 'value2' FROM `table` WHERE `column1` = 'value1' AND `column2` = 'value2' HAVING COUNT(`column1`) = 0 

espero que ayude!

1

Lo que quiere es INSERT INTO table (...) SELECT ... WHERE .... de MySQL 5.6 manual.

En que caso se trata de:

INSERT INTO x_table (instance, user, item) SELECT 919191, 123, 456 
WHERE (SELECT COUNT(*) FROM x_table WHERE user=123 AND item=456) = 0 

O tal vez ya no se está usando cualquier lógica complicada a determiante si desea ejecutar el INSERT o no usted podría establecer una clave UNIQUE en la combinación de estas dos columnas y luego use INSERT IGNORE.

+0

¿Ejecutó su respuesta? Sigo recibiendo 'ERROR 1064 (42000): tienes un error en tu sintaxis SQL; revise el manual que corresponde a su versión del servidor MySQL para la sintaxis correcta para usar cerca de 'where ... '(running 5.6.34) – hlin117

+0

Creo que debe decir' from dual' before 'where'. – hlin117