PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 12.20 » Langage SQL » Fonctions et opérateurs » Comparaisons de lignes et de tableaux

9.23. Comparaisons de lignes et de tableaux

Cette section décrit des constructions adaptées aux comparaisons entre groupes de valeurs. Ces formes sont syntaxiquement liées aux formes des sous-requêtes de la section précédente, mais elles n'impliquent pas de sous-requêtes. Les formes qui impliquent des sous-expressions de tableaux sont des extensions de PostgreSQL ; le reste est compatible avec SQL. Toutes les formes d'expression documentées dans cette section renvoient des résultats booléens (true/false).

9.23.1. IN

expression IN (valeur [, ...])

Le côté droit est une liste entre parenthèses d'expressions. Le résultat est vrai (« true ») si le côté gauche de l'expression est égal à une des expressions du côté droit. C'est une notation raccourcie de

expression = valeur1
OR
expression = valeur2
OR
...

Si l'expression du côté gauche renvoie NULL, ou s'il n'y a pas de valeur égale du côté droit et qu'au moins une expression du côté droit renvoie NULL, le résultat de la construction IN est NULL et non pas faux. Ceci est en accord avec les règles du standard SQL pour les combinaisons booléennes de valeurs NULL.

9.23.2. NOT IN

expression NOT IN (valeur [, ...])

Le côté droit est une liste entre parenthèses d'expressions. Le résultat est vrai (« true ») si le résultat de l'expression du côté gauche est différent de toutes les expressions du côté droit. C'est une notation raccourcie de

expression <> valeur1
AND
expression <> valeur2
AND
...

Si l'expression du côté gauche renvoie NULL, ou s'il existe des valeurs différentes du côté droit et qu'au moins une expression du côté droit renvoie NULL, le résultat de la construction NOT IN est NULL et non pas vrai. Ceci est en accord avec les règles du standard SQL pour les combinaisons booléennes de valeurs NULL.

Astuce

x NOT IN y est équivalent à NOT (x IN y) dans tous les cas. Néanmoins, les valeurs NULL ont plus de chances de surprendre le novice avec NOT IN qu'avec IN. Quand cela est possible, il est préférable d'exprimer la condition de façon positive.

9.23.3. ANY/SOME (array)

expression opérateur ANY (expression tableau)
expression opérateur SOME (expression tableau)

Le côté droit est une expression entre parenthèses qui doit renvoyer une valeur de type array. L'expression du côté gauche est évaluée et comparée à chaque élément du tableau en utilisant l'opérateur donné, qui doit renvoyer un résultat booléen. Le résultat de ANY est vrai (« true ») si un résultat vrai est obtenu. Le résultat est faux (« false ») si aucun résultat vrai n'est trouvé (ce qui inclut le cas spécial du tableau qui ne contient aucun élément).

Si l'expression de tableau ramène un tableau NULL, le résultat de ANY est NULL. Si l'expression du côté gauche retourne NULL, le résultat de ANY est habituellement NULL (bien qu'un opérateur de comparaison non strict puisse conduire à un résultat différent). De plus, si le tableau du côté droit contient des éléments NULL et qu'aucune comparaison vraie n'est obtenue, le résultat de ANY est NULL, et non pas faux (« false ») (là aussi avec l'hypothèse d'un opérateur de comparaison strict). Ceci est en accord avec les règles du standard SQL pour les combinaisons booléennes de valeurs NULL.

SOME est un synonyme de ANY.

9.23.4. ALL (array)

expression opérateur ALL (expression tableau)

Le côté droit est une expression entre parenthèses qui doit renvoyer une valeur de type tableau. L'expression du côté gauche est évaluée et comparée à chaque élément du tableau à l'aide de l'opérateur donné, qui doit renvoyer un résultat booléen. Le résultat de ALL est vrai (« true ») si toutes les comparaisons renvoient vrai (ce qui inclut le cas spécial du tableau qui ne contient aucun élément). Le résultat est faux (« false ») si un résultat faux est trouvé.

Si l'expression de tableau ramène un tableau NULL, le résultat de ALL est NULL. Si l'expression du côté gauche retourne NULL, le résultat de ALL est habituellement NULL (bien qu'un opérateur de comparaison non strict puisse conduire à un résultat différent). De plus, si le tableau du côté droit contient des éléments NULL et qu'aucune comparaison false n'est obtenue, le résultat de ALL est NULL, et non pas true (là aussi avec l'hypothèse d'un opérateur de comparaison strict). Ceci est en accord avec les règles du standard SQL pour les combinaisons booléennes de valeurs NULL.

9.23.5. Comparaison de constructeur de lignes

constructeur_ligne opérateur constructeur_ligne

Chaque côté est un constructeur de lignes, tel que décrit dans la Section 4.2.13. Les deux constructeurs de lignes doivent avoir le même nombre de champs. L'opérateur indiqué est appliqué à chaque paire de champs correspondant. (Comme les champs pourraient être de types différents, ceci signifie qu'un opérateur spécifique différent pourrait être sélectionné pour chaque paire.) Tous les opérateurs sélectionnés doivent être les membres d'une classe d'opérateur B-tree ou être l'inverse d'un membre = d'une classe d'opérateur B-tree, ceci signifiant que la comparaison de constructeur de lignes est seulement possible quand l'opérateur est =, <>, <, <=, >, >=, ou a une sémantique similaire à l'une d'entre elles.

Les cas = et <> fonctionnent légèrement différemment des autres. Les lignes sont considérées comme égales si leurs membres correspondants sont non nuls et égaux ; les lignes sont différentes si des membres correspondants sont non nuls et différents ; autrement, le résultat de la comparaison de ligne est inconnu (NULL).

Pour les cas <, <=, > et >=, les éléments de ligne sont comparés de gauche à droite. La comparaison s'arrête dès qu'une paire d'éléments différents ou NULL est découverte. Si un des éléments de cette paire est NULL, le résultat de la comparaison de la ligne est inconnu, donc NULL ; sinon la comparaison de cette paire d'éléments détermine le résultat. Par exemple, ROW(1,2,NULL) < ROW(1,3,0) est vrai, non NULL, car la troisième paire d'éléments n'est pas considérée.

Note

Avant PostgreSQL 8.2, les cas <, <=, > et >= n'étaient pas gérés d'après les spécifications SQL. Une comparaison comme ROW(a,b) < ROW(c,d) était codée sous la forme a < c AND b < d alors que le bon comportement est équivalent à a < c OR (a = c AND b < d).

constructeur_ligne IS DISTINCT FROM constructeur_ligne

Cette construction est similaire à une comparaison de ligne <>, mais elle ne conduit pas à un résultat NULL pour des entrées NULL. Au lieu de cela, une valeur NULL est considérée comme différente (distincte) d'une valeur non-NULL et deux valeurs NULL sont considérées comme égales (non distinctes). Du coup, le résultat est toujours soit true soit false, jamais NULL.

constructeur_ligne IS NOT DISTINCT FROM constructeur_ligne
   

Cette construction est similaire à une comparaison de lignes =, mais elle ne conduit pas à un résultat NULL pour des entrées NULL. Au lieu de cela, une valeur NULL est considérée comme différente (distincte) d'une valeur non NULL et deux valeurs NULL sont considérées comme identiques (non distinctes). Du coup, le résultat est toujours soit true soit false, jamais NULL.

9.23.6. Comparaison de type composite

record opérateur record
   

Le standard SQL requiert que les comparaisons de ligne renvoient NULL si le résultat dépend de la comparaison de valeurs NUL ou d'une valeur NULL et d'une valeur non NULL. PostgreSQL ne fait cela que lors de la comparaison de deux constructeurs de ligne (comme dans Section 9.23.5) ou lors de la comparaison d'un constructeur de ligne avec la sortie d'une sous-requête (comme dans Section 9.22). Dans les autres contextes où deux valeurs de type composite sont comparées, deux valeurs NULL sont considérées comme identiques et une valeur NULL est considérée comme lus grande qu'une valeur non NULL. Ceci est nécessaire pour avoir un comportement cohérent des tris et de l'indexage pour les types composites.

Chaque côté est évalué et est comparé au niveau de la ligne. Les comparaisons de type composite sont autorisées quand l'opérateur est =, <>, <, <=, > ou >=, ou a une sémantique similaire à l'une d'entre elles. (Pour être précis, un opérateur peut être un opérateur de comparaison de ligne s'il est membre d'une classe d'opérateur B-tree ou s'il est un opérateur de négation du membre = d'une classe d'opérateur B-tree.) Le comportement par défaut des opérateurs ci-dessus est le même que pour IS [ NOT ] DISTINCT FROM pour les constructeurs de lignes (voir Section 9.23.5).

Pour accepter la correspondance des lignes qui incluent des éléments sans classe d'opérateur B-tree par défaut, les opérateurs suivants sont définis pour la comparaison de type composite : *=, *<>, *<, *<=, *> et *>=. Ces opérateurs comparent la représentation binaire interne des deux lignes. Les deux lignes peuvent avoir une représentation binaire différente même si leur comparaison avec l'opérateur d'égalité est vraie. L'ordre des lignes avec ces opérateurs de comparaison est déterminé, mais sans sens particulier. Ces opérateurs sont utilisés en interne pour les vues matérialisées et pourraient être utiles dans d'autres cas très ciblés, comme la réplication. Cependant, elles ne sont généralement pas utiles pour écrire des requêtes.