2016-09-03 1 views
0

Comment puis-je INSERT et ON DUPLICATE KEY mettre à jour toute la ligne si une certaine condition est remplie? Je veux mettre à jour l'ensemble row si VALUES(date_added) est plus ancien alors date_added de la table.INSERT ... ON DUPLICATE KEY UPDATE rangée IF date_added> VALUES (date_added)

Je l'ai vu cet article:

https://thewebfellas.com/blog/conditional-duplicate-key-updates-with-mysql

INSERT INTO daily_events 
    (created_on, last_event_id, last_event_created_at) 
VALUES 
    ('2010-01-19', 23, '2010-01-19 10:23:11') 
ON DUPLICATE KEY UPDATE 
    last_event_id = IF(last_event_created_at < VALUES(last_event_created_at), VALUES(last_event_id), last_event_id), 
    last_event_created_at = IF(last_event_created_at < VALUES(last_event_created_at), VALUES(last_event_created_at), last_event_created_at); 

Mais ce n'est pas un moyen souple d'écrire la déclaration.

plus tard Edit:

D'abord parce que la condition est évaluée pour chaque champ qui sera mis à jour, et, deuxièmement, parce que vous devez faire attention à la position de la ligne qui met à jour la colonne de condition, dans la dernière position la déclaration. Sinon, vous empoisonnez le UPDATE avec des erreurs.

Pour être plus précis, je voudrais cette déclaration, où j'ai inversé les deux lignes UPDATE, pour être valable aussi:

INSERT INTO daily_events(created_on, last_event_id, last_event_created_at) VALUES('2010-01-19', 23, '2010-01-19 10:23:11') ON DUPLICATE KEY UPDATE last_event_created_at = GREATEST(last_event_created_at, VALUES(last_event_created_at)), last_event_id = (CASE WHEN last_event_created_at < VALUES(last_event_created_at) THEN VALUES(last_event_id) ELSE last_event_id END);

Ce n'est pas possible parce que:

Une chose importante à garder à l'esprit lorsque vous utilisez cette approche est que l'ordre dans lequel vous mettez à jour vos champs est très important. J'avais à tort l'impression que les mises à jour avaient lieu dans une assignation de masse après que toute la requête avait été interprétée par MySQL. Mais ils ne le sont pas: les affectations se produisent dans l'ordre où elles apparaissent dans la requête. Lorsque le update est exécuté avec un événement plus récent, le champ last_event_created_at sera mis à jour, mais pas le champ last_event_id. En effet, lorsque le second IF est évalué last_event_created_at a déjà été mis à jour de sorte que last_event_created_at est égal à VALUES(last_event_created_at). Fous hein ?!

+0

Je suis confus par votre question. Votre requête semble faire ce que vous voulez qu'elle fasse. –

+0

Je ne veux pas évaluer la condition deux fois, car je ne peux pas contrôler l'ordre des colonnes. Et à partir de cet exemple, vous pouvez voir que la dernière colonne qui doit être mise à jour est celle qui a la condition dessus. Sinon, vous empoisonneriez la table avec des valeurs incorrectes. – Nick

+0

Qui a donné le "-1"? Il est inutile de downvote sans explication. Vous ne m'empêchez pas de faire l'erreur que vous considérez encore dans le futur. – Nick

Répondre

1

Votre requête semble faire ce que vous voulez, donc je ne comprends pas complètement la question. Vous pourriez simplifiez en utilisant GREATEST():

INSERT INTO daily_events(created_on, last_event_id, last_event_created_at) 
    VALUES('2010-01-19', 23, '2010-01-19 10:23:11') 
ON DUPLICATE KEY UPDATE 
    last_event_id = (CASE WHEN last_event_created_at < VALUES(last_event_created_at) THEN VALUES(last_event_id) ELSE last_event_id END), 
    last_event_created_at = GREATEST(last_event_created_at, VALUES(last_event_created_at)); 

(L'utilisation de CASE est une préférence pour les normes ANSI pour des fonctionnalités équivalentes.)

MySQL ne propose pas une façon de dire « mettre à jour tous ces quand cette condition est remplie ".

+0

Je veux me débarrasser de l'exigence de garder la colonne qui a la condition sur elle (dans ce cas, la colonne 'date_added'). Je vais utiliser cette instruction en Perl, et en écrivant du code pour détecter une certaine colonne et la mettre sur la dernière ligne de l'instruction, cela rendrait le code Perl plus laid, long, inefficace, etc. – Nick

+0

Pour être plus précis, je le ferais Je veux que cette instruction, où j'ai inversé les deux lignes 'UPDATE', soit également valide:' INSERT INTO daily_events (created_on, last_event_id, last_event_created_at) VALUES ('2010-01-19', 23, '2010-01- 19 10:23:11') ON DUPLICATE KEY UPDATE last_event_created_at = GREATEST (last_event_created_at, VALEURS (last_event_created_at)), last_event_id = (CAS QUAND last_event_created_at Nick