web-dev-qa-db-fra.com

Utiliser CASE pour sélectionner des colonnes dans la requête UPDATE?

Je peux utiliser CASE pour choisir les colonnes à afficher dans une requête SELECT (Postgres), comme ceci:

SELECT CASE WHEN val = 0 THEN column_x
            WHEN val = 1 THEN column_y
            ELSE 0
       END AS update, ...

Est-ce que quelque chose de similaire est possible lors de l'exécution d'une requête UPDATE dans Postgres (c'est-à-dire choisir les colonnes à mettre à jour)? Je suppose que non, car je n'ai rien trouvé à ce sujet, mais peut-être que quelqu'un a une alternative intelligente (en plus d'utiliser une procédure ou de mettre à jour chaque colonne à l'aide d'un CASE pour déterminer si la valeur de la colonne doit être affectée à un nouveau ou simplement réaffecté la valeur existante). S'il n'y a pas d'alternative facile, je l'accepterai bien sûr comme réponse également.

Extra info: Dans mon cas, j'ai 14 colonnes potentielles qui peuvent être mises à jour, une seule étant mise à jour par ligne correspondante (le tableau à mettre à jour est joint à un autre dans la requête). Le nombre de lignes à mettre à jour variera très probablement, pourrait être des dizaines ou des centaines. Je pense que des indices sont en place pour les conditions d'adhésion.

13
newenglander

Si vous spécifiez qu'une colonne doit être mise à jour, elle sera toujours mise à jour, mais vous pouvez modifier la valeur que vous entrez conditionnellement et remettre les valeurs d'origine en fonction de vos conditions. Quelque chose comme:

UPDATE some_table
SET    column_x = CASE WHEN should_update_x THEN new_value_for_x ELSE column_x END
     , column_y = CASE WHEN should_update_y THEN new_value_for_y ELSE column_y END
     , column_z = CASE WHEN should_update_z THEN new_value_for_z ELSE column_z END
FROM   ...

Donc, si les conditions ne sont pas bonnes pour une mise à jour d'une colonne particulière, il vous suffit de renvoyer sa valeur actuelle.

Notez que chaque ligne correspond verra voir une mise à jour (même si toutes les colonnes finissent par être réglées sur les valeurs qu'elles ont déjà) sauf vous indiquez explicitement cette circonstance dans votre filtrage Clauses ON et WHERE, qui pourraient être un problème de performances (il y aura une écriture, les index seront mis à jour, les déclencheurs appropriés se déclencheront, ...) s'ils ne sont pas atténués.

26
David Spillett

Combien de combinaisons différentes de colonnes mettre à jour avez-vous? Combien de lignes de la table entière seront mises à jour? Des index sont-ils en place pour un accès rapide aux lignes à mettre à jour?

En fonction des réponses à ces questions, vous pourrez peut-être exécuter plusieurs instructions de mise à jour, une pour chaque colonne que vous souhaitez mettre à jour et placer la condition sur la valeur de cette colonne dans la clause where de la mise à jour afin que zéro ligne soit mise à jour si cette colonne a la mauvaise valeur.

Essayez de penser basé sur un ensemble, ne supposez pas que la mise à jour doit mettre à jour une seule ligne trouvée par la clé primaire.

5
Colin 't Hart