web-dev-qa-db-fra.com

MySQL Insertion conditionnelle

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. 

83
The Unknown

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.

99
Jonathan Leffler

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

42
MrD

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;
25
temple

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.

10
Alex Martelli

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 !

2
Gew

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.

1
martin

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
1
NickZoic

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.

1
Beatles1692

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
0
Danny

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
Keith Becker
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 ...

0
Rick J

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
0
xsubira