J'ai de la difficulté à former un INSERT conditionnel
J'ai x_table avec des colonnes (instance, utilisateur, élément) où ID instance est unique. Je souhaite insérer une nouvelle ligne uniquement si l'utilisateur ne dispose pas déjà 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.
Si votre SGBD n'impose pas de restrictions sur la table que vous avez sélectionnée lors de l'exécution d'une insertion, 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 cela, dual
est une table avec une seule ligne (trouvée à l'origine dans Oracle, maintenant aussi dans mysql). La logique est que l'instruction SELECT génère une seule ligne de données avec les valeurs requises, mais uniquement lorsque les valeurs ne sont pas déjà trouvées.
Vous pouvez également consulter l'instruction MERGE.
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 (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 UNIQUE(user, item)
, faites:
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 rien faire lorsqu'il y a des doublons.
Si vous ne souhaitez 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
J'espère que ça aide !
Ce que vous voulez, c'est INSERT INTO table (...) SELECT ... WHERE ...
. à partir de Manuel MySQL 5.6 .
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 souhaitez exécuter la variable INSERT
ou non, vous pouvez simplement définir une clé UNIQUE
sur la combinaison de ces deux colonnes, puis utiliser INSERT IGNORE
.
Si vous ajoutez une contrainte qui (x_table.user, x_table.item) est unique, l'insertion d'une autre ligne avec le même utilisateur et le même élément é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 placer une contrainte/index unique sur vos colonnes afin qu'aucune donnée en double ne puisse être insérée par erreur.
Légère modification de la réponse d'Alex, vous pouvez également simplement référencer la valeur de colonne existante:
Insert into x_table (instance, user, item) values (919191, 123, 456)
ON DUPLICATE KEY UPDATE user=user
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)
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 base de données ...
Donc, celui-ci représente 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