Inserción condicional de MySQL
Estoy teniendo dificultades para formar un INSERTO condicional
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 dado.
Por ejemplo, tratando de insertar instance = 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.
12 answers
Si su DBMS no impone limitaciones sobre la tabla de la que selecciona cuando ejecuta un insert, 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 (que se encuentra originalmente en Oracle, ahora también en otros lugares). La lógica es que la instrucción SELECT genera una sola fila de datos con los valores requeridos, pero solo cuando los valores no se encuentran ya.
Alternativamente, mira la instrucción MERGE.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-27 04:31:08
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 único con CREATE UNIQUE INDEX user_item ON x_table (user, item)
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-25 06:52:03
¿Alguna vez has probado 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;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-15 21:35:16
Con un UNIQUE(user, item)
, haga:
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 coincidir con la sintaxis de la cláusula ON DUPLICATE
sin hacer realmente nada cuando hay duplicados.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-27 04:37:40
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 que ayude !
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-29 11:23:48
Si agrega una restricción que (x_table.usuario, x_table.item) es único, luego se producirá un error al insertar otra fila con el mismo usuario y el mismo item.
Eg:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-27 04:00:26
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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-27 04:03:02
Lo que quieres es INSERT INTO table (...) SELECT ... WHERE ...
. desde MySQL 5.6 manual .
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 se debe ejecutar el INSERT
o no, solo podría establecer una tecla UNIQUE
en la combinación de estas dos columnas y luego usar INSERT IGNORE
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-27 18:49:13
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 su BD...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-27 03:56:41
Una ligera modificación en la respuesta de Alex, también puede 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-25 05:50:04
Así que este es 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-13 13:01:09
Puede utilizar la siguiente solución para resolver su problema:
INSERT INTO x_table(instance, user, item)
SELECT 919191, 123, 456
FROM dual
WHERE 123 NOT IN (SELECT user FROM x_table)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-16 00:28:31