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.
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.
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)
.
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;
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.
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 !
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
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.
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
.
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...
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
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
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)