update - Inserción condicional de MySQL
select insert mysql ejemplos (11)
Estoy teniendo dificultades para formar un INSERT condicionado
Tengo x_table con columnas (instancia, usuario, elemento) donde el ID de instancia es único. Quiero insertar una nueva fila solo si el usuario ya no tiene un elemento determinado.
Por ejemplo, tratando de insertar instancia = 919191 usuario = 123 elemento = 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.
¿Alguna vez has 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;
Aunque es bueno verificar la duplicación antes de insertar sus datos, le sugiero que ponga una restricción / índice único en sus columnas para que no se puedan insertar datos duplicados por error.
Con UNIQUE(user, item)
, haz:
Insert into x_table (instance, user, item) values (919191, 123, 456)
ON DUPLICATE KEY UPDATE user=123
el user=123
bit es un "no-op" para hacer coincidir la sintaxis de la cláusula ON DUPLICATE
sin hacer realmente nada cuando hay duplicados.
En caso de que no desee 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 eso ayude !
Entonces este 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
Leve modificación a la respuesta de Alex, también podría simplemente 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
Lo que quieres es INSERT INTO table (...) SELECT ... WHERE ...
del manual de MySQL 5.6 .
En tu caso es:
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 que no está utilizando ninguna lógica complicada para determinar si ejecutar el INSERT
o no, puede simplemente establecer una clave UNIQUE
en la combinación de estas dos columnas y luego usar INSERT IGNORE
.
Si agrega una restricción que (x_table.user, x_table.item) es única, la inserción de otra fila con el mismo usuario y elemento fallará.
p.ej:
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
Si su DBMS no impone limitaciones a la tabla que selecciona cuando ejecuta una inserción, intente:
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 (se encuentra originalmente en Oracle, ahora también en otros lugares). 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.
Alternativamente, mira la declaración MERGE.
También puede usar INSERT IGNORE
que ignora silenciosamente la inserción en lugar de actualizar o insertar una fila cuando tiene un índice único en (usuario, elemento).
La consulta se verá así:
INSERT IGNORE INTO x_table(instance, user, item) VALUES (919191, 123, 456)
Puede agregar el índice exclusivo con CREATE UNIQUE INDEX user_item ON x_table (user, item)
.
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 dependiendo de tu DB ...