SQL insérer dans la table seulement si l'enregistrement n'existe pas [dupliquer]
cette question a déjà une réponse ici:
- vérifier si une rangée existe, sinon inscrire 11 réponses
- MySQL Conditionnelle Insérer 12 réponses
je veux exécuter un ensemble de requêtes pour insérer des données dans une table SQL, mais seulement si l'enregistrement satisfaisant certains critères sont respectés. Le tableau comporte 4 champs: id
(primaire), fund_id
, date
et price
j'ai 3 champs dans la requête: fund_id
, date
et price
.
Donc ma requête serait quelque chose comme ceci:
INSERT INTO funds (fund_id, date, price)
VALUES (23, '2013-02-12', 22.43)
WHERE NOT EXISTS (
SELECT *
FROM funds
WHERE fund_id = 23
AND date = '2013-02-12'
);
Donc Je ne veulent insérer les données que si un enregistrement correspondant aux fund_id
et date
n'existe pas déjà. Si ce qui précède est correct, il me semble que c'est un moyen tout à fait inefficace de réaliser ceci puisqu'une instruction select supplémentaire doit être exécutée à chaque fois.
y a-t-il une meilleure façon d'atteindre ce qui précède?
modifier: à des fins de clarification, ni fund_id
ni date
ne sont des champs uniques; les enregistrements partageant le même fund_id ou la même date n'existeront pas. l'enregistrement devrait avoir à la fois le même nom_de_fonds et la même date qu'un autre.
3 réponses
cela pourrait être une solution simple pour atteindre cet objectif:
INSERT INTO funds (ID, date, price)
SELECT 23, DATE('2013-02-12'), 22.5
FROM dual
WHERE NOT EXISTS (SELECT 1
FROM funds
WHERE ID = 23
AND date = DATE('2013-02-12'));
p. S. alternativement (si ID
est une clé primaire):
INSERT INTO funds (ID, date, price)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE ID = 23; -- or whatever you need
voir ce violon .
bien que la réponse que j'ai initialement indiquée comme étant choisie soit correcte et qu'elle permette d'obtenir ce que j'ai demandé, il y a une meilleure façon de le faire (ce que d'autres ont reconnu mais n'ont pas fait). Un indice composite unique doit être créé sur la table comprenant fund_id
et date
.
ALTER TABLE funds ADD UNIQUE KEY `fund_date` (`fund_id`, `date`);
, Puis lors de l'insertion d'un enregistrement d'ajouter la condition lorsqu'un conflit est détecté:
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = `price`; --this keeps the price what it was (no change to the table) or:
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = 22.5; --this updates the price to the new value
cela fournira une bien meilleure performance à un sous-requête et la structure de la table est supérieure. Il vient avec la mise en garde que vous ne pouvez pas avoir des valeurs nulles dans vos colonnes de clés uniques car ils sont encore traités comme des valeurs par MySQL.
en supposant que vous ne pouvez pas modifier DDL (pour créer une contrainte unique) ou sont limités à être en mesure d'écrire DML puis de vérifier un résultat null sur filtré de vos valeurs par rapport à l'ensemble de la table
VIOLON
insert into funds (ID, date, price)
select
T.*
from
(select 23 ID, '2013-02-12' date, 22.43 price) T
left join
funds on funds.ID = T.ID and funds.date = T.date
where
funds.ID is null