PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Instruction de mise à jour à l'aide d'une clause WHERE contenant des colonnes avec des valeurs nulles

Puisque null = null est évalué à false vous devez vérifier si deux champs sont tous les deux null en plus du contrôle d'égalité :

UPDATE table_one SET table_one.x = table_two.y 
FROM table_two
WHERE 
    (table_one.invoice_number = table_two.invoice_number 
        OR (table_one.invoice_number is null AND table_two.invoice_number is null))
    AND
    (table_one.submitted_by = table_two.submitted_by 
        OR (table_one.submitted_by is null AND table_two.submitted_by is null))
    AND 
    -- etc

Vous pouvez également utiliser le coalesce fonction plus lisible :

UPDATE table_one SET table_one.x = table_two.y 
FROM table_two
WHERE 
    coalesce(table_one.invoice_number, '') = coalesce(table_two.invoice_number, '')
    AND coalesce(table_one.submitted_by, '') = coalesce(table_two.submitted_by, '')
    AND -- etc

Mais vous devez faire attention aux valeurs par défaut (dernier argument de coalesce ).
Son type de données doit correspondre au type de colonne (afin que vous ne finissiez pas par comparer des dates avec des nombres par exemple) et la valeur par défaut doit être telle qu'elle n'apparaisse pas dans les données
Par exemple coalesce(null, 1) = coalesce(1, 1) est une situation que vous voudriez éviter.

Mise à jour (concernant les performances) :

Seq Scan on table_two - cela suggère que vous n'avez aucun index sur table_two .
Donc, si vous mettez à jour une ligne dans table_one puis pour trouver une ligne correspondante dans table_two la base de données doit essentiellement parcourir toutes les lignes une par une jusqu'à ce qu'elle trouve une correspondance.
Les lignes correspondantes pourraient être trouvées beaucoup plus rapidement si les colonnes pertinentes étaient indexées.

D'un autre côté si table_one a des index qui ralentissent la mise à jour.
Selon ce guide des performances :

Une autre suggestion du même guide qui pourrait être utile est :

Ainsi, par exemple, si table_one un id colonne, vous pouvez ajouter quelque chose comme

and table_one.id between x and y

à where condition et exécutez la requête plusieurs fois en changeant les valeurs de x et y afin que toutes les lignes soient couvertes.

Vous voudrez peut-être être prudent lorsque vous utilisez le ANALYZE option avec EXPLAIN lorsqu'il s'agit d'instructions avec des effets secondaires.Selon la documentation :