MySQL Conditional Insert

je vais avoir un moment difficile de former un conditionnel INSÉRER

j'ai x_table avec les colonnes (instance, utilisateur, élément) où l'ID d'instance est unique. Je veux insérer une nouvelle ligne uniquement si l'utilisateur ne dispose pas d'un élément donné.

par exemple, essayer d'insérer 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 

toute aide ou orientation dans la bonne direction serait grandement appréciée.

80
demandé sur The Unknown 2009-05-27 07:48:00

12 réponses

si votre SGBD n'impose pas de limites à la table que vous sélectionnez Lorsque vous exécutez un insert, essayez:

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 ceci, dual est une table avec une seule rangée (trouvée à L'origine dans Oracle, maintenant ailleurs aussi). La logique est que L'instruction SELECT génère une seule rangée de données avec les valeurs requises, mais seulement lorsque les valeurs ne sont pas déjà trouvées.

alternativement, regardez la déclaration de fusion.

98
répondu Jonathan Leffler 2009-05-27 04:31:08

vous pouvez également utiliser INSERT IGNORE qui ignore silencieusement l'insertion au lieu de mettre à jour ou d'insérer une ligne lorsque vous avez un index unique SUR (utilisateur, élément).

la requête ressemblera à ceci:

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

vous pouvez ajouter l'index unique avec CREATE UNIQUE INDEX user_item ON x_table (user, item) .

42
répondu MrD 2012-04-25 06:52:03

Avez-vous déjà essayé quelque chose comme ça?

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;
24
répondu temple 2011-10-15 21:35:16

avec un UNIQUE(user, item) , do:

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

le bit user=123 est un "no-op" pour correspondre à la syntaxe de la clause ON DUPLICATE sans réellement faire quoi que ce soit quand il y a des doublons.

10
répondu Alex Martelli 2009-05-27 04:37:40

dans le cas où vous ne voulez pas définir une contrainte unique, cela fonctionne comme un charme:

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

Espère que cela aide !

2
répondu Gew 2014-08-29 11:23:48

si vous ajoutez une contrainte qui (x_table.l'utilisateur, x_table.item) est unique, puis l'insertion d'une autre ligne avec le même utilisateur et l'article échouera.

par exemple:

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
1
répondu NickZoic 2009-05-27 04:00:26

bien qu'il soit bon de vérifier la duplication avant d'insérer vos données, je vous suggère de mettre une contrainte/index unique sur vos colonnes afin qu'aucune donnée dupliquée ne puisse être insérée par erreur.

1
répondu Beatles1692 2009-05-27 04:03:02

ce que vous voulez est INSERT INTO table (...) SELECT ... WHERE ... . de MySQL 5.6 manuel .

dans votre cas c'est:

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

ou peut-être que puisque vous n'utilisez pas de logique compliquée pour déterminer si vous devez exécuter le INSERT ou non, vous pouvez simplement mettre une touche UNIQUE sur la combinaison de ces deux colonnes et ensuite utiliser INSERT IGNORE .

1
répondu martin 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 syntaxe peut varier en fonction de votre DB...

0
répondu Rick J 2009-05-27 03:56:41

légère modification à la réponse D'Alex, vous pouvez aussi simplement faire référence à la valeur de la colonne existante:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
  ON DUPLICATE KEY UPDATE user=user
0
répondu Danny 2011-07-25 05:50:04

donc celui-ci est pour 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
0
répondu xsubira 2013-03-13 13:01:09

Vous pouvez utiliser la solution suivante pour résoudre votre problème:

INSERT INTO x_table(instance, user, item) 
    SELECT 919191, 123, 456
        FROM dual
        WHERE 123 NOT IN (SELECT user FROM x_table)
0
répondu Keith Becker 2018-08-16 00:28:31