PostgreSQLLa base de données la plus sophistiquée au monde.

9.21. 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.21.1. IN

expression IN (valeur [, ...])

Le côté droit est une liste entre parenthèses d'expressions scalaires. 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.21.2. NOT IN

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

Le côté droit est une liste entre parenthèses d'expressions scalaires. 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 du SQL pour les combinaisons booléennes de valeurs NULL.

[Astuce]

Astuce

x NOT IN y est équivalent à NOT (x IN y) dans tout 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.21.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.21.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.21.5. Comparaison de lignes entières

constructeur_ligne opérateur constructeur_ligne

Chaque côté est un constructeur de lignes, tel que décrit dans la Section 4.2.12, « Constructeurs de lignes ». Les deux valeurs de lignes doivent avoir le même nombre de lignes. Chaque côté est évalué. Ils sont alors comparés sur toute la ligne. Les comparaisons de lignes sont autorisées quand l'opérateur est =, <>, <, <=, >, >=, ou a une sémantique similaire à l'un d'eux. (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érateurs B-Tree ou est le négateur du membre = d'une classe d'opérateurs B-Tree.)

Les cas = et <> fonctionnent légèrement différemment des autres. Les lignes sont considérées é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]

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 différente (distincte) d'une valeur non-NULL et deux valeurs NULL sont considérées é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 différente (distincte) d'une valeur non NULL et deux valeurs NULL sont considérées identiques (non distinctes). Du coup, le résultat est toujours soit true soit false, jamais NULL.

[Note]

Note

Le standard SQL requiert qu'une comparaison d'une ligne complète renvoit NULL si le résultat dépend de la comparaison de deux valeurs NULL ou d'une valeur NULL et d'une valeur non NULL. PostgreSQL™ le fait en comparant le résultat de deux constructeurs de lignes ou en comparant un constructeur de ligne avec le résultat d'une sous-requête (comme dans Section 9.20, « Expressions de sous-requêtes »). Dans d'autres contextes où deux valeurs de type composite sont comparées, deux champs NULL sont considérés égaux, et un champ NULL est considéré plus grand qu'un champ non NULL. Ceci est nécessaire pour voir un comportement de tri et d'indexage cohérent pour les types composites.