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

Version anglaise

SELECT

SELECT, TABLE, WITH — rĂ©cupĂšre des lignes d'une table ou d'une vue

Synopsis

[ WITH [ RECURSIVE ] requĂȘte_with [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ [ AS ] nom_d_affichage ] [, ...]
    [ FROM éléments_from [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ WINDOW nom_window AS ( définition_window ) [, ...] ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
    [ ORDER BY expression [ ASC | DESC | USING opérateur ] [ NULLS { FIRST | LAST } ] [, ...] ]
    [ LIMIT { nombre | ALL } ]
    [ OFFSET début ] [ ROW | ROWS ] ]
    [ FETCH { FIRST | NEXT } [ total ] { ROW | ROWS } ONLY ]
    [ FOR { UPDATE | SHARE } [ OF nom_table [, ...] ] [ NOWAIT ] [...] ]

avec Ă©lĂ©ments_from qui peut ĂȘtre :

    [ ONLY ] nom_table [ * ] [ [ AS ] alias [ ( alias_colonne [, ...] ) ] ]
    ( select ) [ AS ] alias [ ( alias_colonne [, ...] ) ]
    nom_requĂȘte_with [ [ AS ] alias [ ( alias_colonne [, ...] ) ] ]
    nom_fonction ( [ argument [, ...] ] ) [ AS ] alias [ ( alias_colonne [, ...] | définition_colonne [, ...] ) ]
    nom_fonction ( [ argument [, ...] ] ) AS ( définition_colonne [, ...] )
    éléments_from [ NATURAL ] type_jointure éléments_from [ ON condition_jointure | USING ( colonne_jointure [, ...] ) ]

et requĂȘte_with est :

    nom_requĂȘte_with [ ( nom_colonne [, ...] ) ] AS ( select | valeurs | insert | update | delete )

TABLE [ ONLY ] nom_table [ * ]

Description

SELECT rĂ©cupĂšre des lignes de zĂ©ro ou plusieurs tables. Le traitement gĂ©nĂ©ral de SELECT est le suivant :

  1. Toutes les requĂȘtes dans la liste WITH sont Ă©valuĂ©es. Elles jouent le rĂŽle de tables temporaires qui peuvent ĂȘtre rĂ©fĂ©rencĂ©es dans la liste FROM. Une requĂȘte WITH qui est rĂ©fĂ©rencĂ©e plus d'une fois dans FROM n'est calculĂ©e qu'une fois (voir la section intitulĂ©e « Clause WITH Â» ci-dessous).

  2. Tous les Ă©lĂ©ments de la liste FROM sont calculĂ©s. (Chaque Ă©lĂ©ment dans la liste FROM est une table rĂ©elle ou virtuelle.) Si plus d'un Ă©lĂ©ment sont spĂ©cifiĂ©s dans la liste FROM, ils font l'objet d'une jointure croisĂ©e (cross-join). (Voir la section intitulĂ©e « Clause FROM Â» ci-dessous.)

  3. Si la clause WHERE est spĂ©cifiĂ©e, toutes les lignes qui ne satisfont pas les conditions sont Ă©liminĂ©es de l'affichage. (Voir la section intitulĂ©e « Clause WHERE Â» ci-dessous.)

  4. Si la clause GROUP BY est spĂ©cifiĂ©e, l'affichage est divisĂ© en groupes de lignes qui correspondent Ă  une ou plusieurs valeurs. Si la clause HAVING est prĂ©sente, elle Ă©limine les groupes qui ne satisfont pas la condition donnĂ©e. (Voir la section intitulĂ©e « Clause GROUP BY Â» et la section intitulĂ©e « Clause HAVING Â» ci-dessous.)

  5. Les lignes retournĂ©es sont traitĂ©es en utilisant les expressions de sortie de SELECT pour chaque ligne ou groupe de ligne sĂ©lectionnĂ©. (Voir la section intitulĂ©e « Liste SELECT Â» ci-dessous.)

  6. SELECT DISTINCT élimine du résultat les lignes en double. SELECT DISTINCT ON élimine les lignes qui correspondent sur toute l'expression spécifiée. SELECT ALL (l'option par défaut) retourne toutes les lignes, y compris les doublons. (cf. DISTINCT Clause ci-dessous.)

  7. En utilisant les opĂ©rateurs UNION, INTERSECT et EXCEPT, l'affichage de plusieurs instructions SELECT peut ĂȘtre combinĂ© pour former un ensemble unique de rĂ©sultats. L'opĂ©rateur UNION renvoie toutes les lignes qui appartiennent, au moins, Ă  l'un des ensembles de rĂ©sultats. L'opĂ©rateur INTERSECT renvoie toutes les lignes qui sont dans tous les ensembles de rĂ©sultats. L'opĂ©rateur EXCEPT renvoie les lignes qui sont prĂ©sentes dans le premier ensemble de rĂ©sultats mais pas dans le deuxiĂšme. Dans les trois cas, les lignes dupliquĂ©es sont Ă©liminĂ©es sauf si ALL est spĂ©cifiĂ©. Le mot-clĂ© supplĂ©mentaire DISTINCT peut ĂȘtre ajoutĂ© pour signifier explicitement que les lignes en doublon sont Ă©liminĂ©es. Notez bien que DISTINCT est lĂ  le comportement par dĂ©faut, bien que ALL soit le dĂ©faut pour la commande SELECT. (Voir la section intitulĂ©e « Clause UNION Â», la section intitulĂ©e « Clause INTERSECT Â» et la section intitulĂ©e « Clause EXCEPT Â» ci-dessous.)

  8. Si la clause ORDER BY est spĂ©cifiĂ©e, les lignes renvoyĂ©es sont triĂ©es dans l'ordre spĂ©cifiĂ©. Si ORDER BY n'est pas indiquĂ©, les lignes sont retournĂ©es dans l'ordre qui permet la rĂ©ponse la plus rapide du systĂšme. (Voir la section intitulĂ©e « Clause ORDER BY Â» ci-dessous.)

  9. Si les clauses LIMIT (ou FETCH FIRST) ou OFFSET sont spĂ©cifiĂ©es, l'instruction SELECT ne renvoie qu'un sous-ensemble de lignes de rĂ©sultats. (Voir la section intitulĂ©e « Clause LIMIT Â» ci-dessous.)

  10. Si la clause FOR UPDATE ou FOR SHARE est spĂ©cifiĂ©e, l'instruction SELECT verrouille les lignes sĂ©lectionnĂ©es contre les mises Ă  jour concurrentes. (Voir la section intitulĂ©e « Clause FOR UPDATE/FOR SHARE Â» ci-dessous.)

Le droit SELECT sur chaque colonne utilisée dans une commande SELECT est nécessaire pour lire ses valeurs. L'utilisation de FOR UPDATE ou de FOR SHARE requiert en plus le droit UPDATE (pour au moins une colonne de chaque table sélectionnée).

ParamĂštres

Clause WITH

La clause WITH vous permet de spĂ©cifier une ou plusieurs sous-requĂȘtes qui peuvent ĂȘtre utilisĂ©es par leur nom dans la requĂȘte principale. Les sous-requĂȘtes se comportent comme des tables temporaires ou des vues pendant la durĂ©e d'exĂ©cution de la requĂȘte principale. Chaque sous-requĂȘte peut ĂȘtre un ordre SELECT, VALUES, INSERT, UPDATE ou bien DELETE. Lorsque vous Ă©crivez un ordre de modification de donnĂ©es (INSERT, UPDATE ou DELETE) dans une clause WITH, il est habituel d'inclure une clause RETURNING. C'est la sortie de cette clause RETURNING, et non pas la table sous-jacente que l'ordre modifie, qui donne lieu Ă  la table temporaire lue par la requĂȘte principale. Si la clause RETURNING est omise, l'ordre est tout de mĂȘme exĂ©cutĂ©, mais il ne produit pas de sortie ; il ne peut donc pas ĂȘtre rĂ©fĂ©rencĂ© comme une table par la requĂȘte principale.

Un nom (sans qualification de schĂ©ma) doit ĂȘtre spĂ©cifiĂ© pour chaque requĂȘte WITH. En option, une liste de noms de colonnes peut ĂȘtre spĂ©cifiĂ© ; si elle est omise, les noms de colonnes sont dĂ©duites de la sous-requĂȘte.

Si RECURSIVE est spĂ©cifiĂ©, la sous-requĂȘte SELECT peut se rĂ©fĂ©rencer elle mĂȘme. Une sous-requĂȘte de ce type doit avoir la forme

terme_non_récursif UNION [ ALL | DISTINCT ] terme_récursif

oĂč l'auto-rĂ©fĂ©rence rĂ©cursive doit apparaĂźtre dans la partie droite de l'UNION. Seule une auto-rĂ©fĂ©rence rĂ©cursive est autorisĂ©e par requĂȘte. Les ordres de modification rĂ©cursifs ne sont pas supportĂ©s, mais vous pouvez utiliser le rĂ©sultat d'une commande SELECT rĂ©cursive dans un ordre de modification. Voir Section 7.8, « RequĂȘtes WITH (Common Table Expressions) Â» pour un exemple.

Un autre effet de RECURSIVE est que les requĂȘtes WITH n'ont pas besoin d'ĂȘtre ordonnĂ©es : une requĂȘte peut en rĂ©fĂ©rencer une autre qui se trouve plus loin dans la liste (toutefois, les rĂ©fĂ©rences circulaires, ou rĂ©cursion mutuelle, ne sont pas implĂ©mentĂ©es). Sans RECURSIVE, les requĂȘtes WITH ne peuvent rĂ©fĂ©rencer d'autres requĂȘtes WITH soƓurs que si elles sont dĂ©clarĂ©es avant dans la liste WITH.

Une propriĂ©tĂ© clĂ© des requĂȘtes WITH est qu'elles ne sont Ă©valuĂ©es qu'une seule fois par exĂ©cution de la requĂȘte principale, mĂȘme si la requĂȘte principale les utilise plus d'une fois. En particulier, vous avez la garantie que les traitements de modification de donnĂ©es sont exĂ©cutĂ©s une seule et unique fois, que la requĂȘte principale lise tout ou partie de leur sortie.

Tout se passe comme si la requĂȘte principale et les requĂȘtes WITH Ă©taient toutes exĂ©cutĂ©es en mĂȘme temps. Ceci a pour consĂ©quence que les effets d'un ordre de modification dans une clause WITH ne peuvent pas ĂȘtre vues des autres parties de la requĂȘte, sauf en lisant la sortie de RETURNING. Si deux de ces ordres de modifications tentent de modifier la mĂȘme ligne, les rĂ©sultats sont imprĂ©visibles.

Voir Section 7.8, « RequĂȘtes WITH (Common Table Expressions) Â» pour plus d'informations.

Clause FROM

La clause FROM spécifie une ou plusieurs tables source pour le SELECT. Si plusieurs sources sont spécifiées, le résultat est un produit cartésien (jointure croisée) de toutes les sources. Mais habituellement, des conditions de qualification sont ajoutées pour restreindre les lignes renvoyées à un petit sous-ensemble du produit cartésien.

La clause FROM peut contenir les Ă©lĂ©ments suivants :

nom_table

Le nom (Ă©ventuellement qualifiĂ© par le nom du schĂ©ma) d'une table ou vue existante. Si ONLY est spĂ©cifiĂ© avant le nom de la table, seule cette table est parcourue. Dans le cas contraire, la table et toutes ses tables filles (s'il y en a) sont parcourues. En option, * peut ĂȘtre ajoutĂ© aprĂšs le nom de la table pour indiquer explicitement que les tables filles sont inclues.

alias

Un nom de substitution pour l'Ă©lĂ©ment FROM contenant l' alias. Un alias est utilisĂ© par briĂšvetĂ© ou pour lever toute ambiguĂŻtĂ© lors d'auto-jointures (la mĂȘme table est parcourue plusieurs fois). Quand un alias est fourni, il cache complĂštement le nom rĂ©el de la table ou fonction ; par exemple, avec FROM truc AS, le reste du SELECT doit faire rĂ©fĂ©rence Ă  cet Ă©lĂ©ment de FROM par f et non pas par truc. Si un alias est donnĂ©, une liste d' alias de colonnes peut aussi ĂȘtre saisi comme noms de substitution pour diffĂ©rentes colonnes de la table.

select

Un sous-SELECT peut apparaĂźtre dans la clause FROM. Il agit comme si sa sortie Ă©tait transformĂ©e en table temporaire pour la durĂ©e de cette seule commande SELECT. Le sous-SELECT doit ĂȘtre entourĂ© de parenthĂšses et un alias doit lui ĂȘtre fourni. Une commande VALUES(7) peut aussi ĂȘtre utilisĂ©e ici.

requĂȘte_with

Une requĂȘte WITH est rĂ©fĂ©rencĂ©e par l'Ă©criture de son nom, exactement comme si le nom de la requĂȘte Ă©tait un nom de table (en fait, la requĂȘte WITH cache toutes les tables qui auraient le mĂȘme nom dans la requĂȘte principale. Si nĂ©cessaire, vous pouvez accĂ©der Ă  une table rĂ©elle du mĂȘme nom en prĂ©cisant le schĂ©ma du nom de la table). Un alias peut ĂȘtre indiquĂ© de la mĂȘme façon que pour une table.

nom_fonction

Des appels de fonctions peuvent apparaĂźtre dans la clause FROM. (Cela est particuliĂšrement utile pour les fonctions renvoyant des ensembles de rĂ©sultats, mais n'importe quelle fonction peut ĂȘtre utilisĂ©e.) Un appel de fonction agit comme si la sortie Ă©tait transformĂ©e en table temporaire pour la durĂ©e de cette seule commande SELECT. Un alias peut aussi ĂȘtre utilisĂ©. Si un alias est donnĂ©, une liste d' alias de colonnes peut ĂȘtre ajoutĂ©e pour fournir des noms de substitution pour un ou plusieurs attributs du type composĂ© de retour de la fonction. Si la fonction a Ă©tĂ© dĂ©finie comme renvoyant le type de donnĂ©es record, alors un alias ou un mot clĂ© AS doit ĂȘtre prĂ©sent, suivi par une liste de dĂ©finitions de colonnes de la forme ( nom_colonne type_donnĂ©es [, ... ] ). La liste de dĂ©finitions de colonnes doit correspondre au nombre rĂ©el et aux types rĂ©els des colonnes renvoyĂ©es par la fonction.

type_jointure

Un des éléments

  • [ INNER ] JOIN

  • LEFT [ OUTER ] JOIN

  • RIGHT [ OUTER ] JOIN

  • FULL [ OUTER ] JOIN

  • CROSS JOIN

Pour les types de jointures INNER et OUTER, une condition de jointure doit ĂȘtre spĂ©cifiĂ©e, Ă  choisir parmi NATURAL, ON condition_jointure ou USING (colonne_jointure [, ...]). Voir ci-dessous pour la signification. Pour CROSS JOIN, aucune de ces clauses ne doit apparaĂźtre.

Une clause JOIN combine deux Ă©lĂ©ments FROM. Les parenthĂšses peuvent ĂȘtre utilisĂ©es pour dĂ©terminer l'ordre d'imbrication. En l'absence de parenthĂšses, les JOIN sont imbriquĂ©s de gauche Ă  droite. Dans tous les cas, JOIN est plus prioritaire que les virgules sĂ©parant les Ă©lĂ©ments FROM.

CROSS JOIN et INNER JOIN produisent un simple produit cartésien. Le résultat est identique à celui obtenu lorsque les deux éléments sont listés au premier niveau du FROM, mais restreint par la condition de jointure (si elle existe). CROSS JOIN est équivalent à INNER JOIN ON (TRUE), c'est-à-dire qu'aucune ligne n'est supprimée par qualification. Ces types de jointure sont essentiellement une aide à la notation car ils ne font rien de plus qu'un simple FROM et WHERE.

LEFT OUTER JOIN renvoie toutes les lignes du produit cartésien qualifié (c'est-à-dire toutes les lignes combinées qui satisfont la condition de jointure), plus une copie de chaque ligne de la table de gauche pour laquelle il n'y a pas de ligne à droite qui satisfasse la condition de jointure. La ligne de gauche est étendue à la largeur complÚte de la table jointe par insertion de valeurs NULL pour les colonnes de droite. Seule la condition de la clause JOIN est utilisée pour décider des lignes qui correspondent. Les conditions externes sont appliquées aprÚs coup.

À l'inverse, RIGHT OUTER JOIN renvoie toutes les lignes jointes plus une ligne pour chaque ligne de droite sans correspondance (complĂ©tĂ©e par des NULL pour le cĂŽtĂ© gauche). C'est une simple aide Ă  la notation car il est aisĂ©ment convertible en LEFT en inversant les entrĂ©es gauche et droite.

FULL OUTER JOIN renvoie toutes les lignes jointes, plus chaque ligne gauche sans correspondance (étendue par des NULL à droite), plus chaque ligne droite sans correspondance (étendue par des NULL à gauche).

ON condition_jointure

condition_jointure est une expression qui retourne une valeur de type boolean (comme une clause WHERE) qui spécifie les lignes d'une jointure devant correspondre.

USING (colonne_jointure [, ...])

Une clause de la forme USING ( a, b, ... ) est un raccourci pour ON table_gauche.a = table_droite.a AND table_gauche.b = table_droite.b .... De plus, USING implique l'affichage d'une seule paire des colonnes correspondantes dans la sortie de la jointure.

NATURAL

NATURAL est un raccourci pour une liste USING qui mentionne toutes les colonnes de mĂȘme nom dans les deux tables. S'il n'y a pas de noms de colonnes communs, NATURAL est Ă©quivalent Ă  ON TRUE.

Clause WHERE

La clause WHERE optionnelle a la forme générale

WHERE condition

oĂč condition est une expression dont le rĂ©sultat est de type boolean. Toute ligne qui ne satisfait pas cette condition est Ă©liminĂ©e de la sortie. Une ligne satisfait la condition si elle retourne vrai quand les valeurs rĂ©elles de la ligne sont substituĂ©es Ă  toute rĂ©fĂ©rence de variable.

Clause GROUP BY

La clause GROUP BY optionnelle a la forme générale

GROUP BY expression [, ...]

GROUP BY condense en une seule ligne toutes les lignes sĂ©lectionnĂ©es qui partagent les mĂȘmes valeurs pour les expressions regroupĂ©es. expression peut ĂȘtre le nom d'une colonne en entrĂ©e, le nom ou le numĂ©ro d'une colonne en sortie (Ă©lĂ©ment de la liste SELECT), ou une expression quelconque formĂ©e de valeurs de colonnes en entrĂ©e. En cas d'ambiguĂŻtĂ©, un nom de GROUP BY est interprĂ©tĂ© comme un nom de colonne en entrĂ©e, non en sortie.

Les fonctions d'agrégat, si utilisées, sont calculées pour toutes les lignes composant un groupe, produisant une valeur séparée pour chaque groupe (alors que sans GROUP BY, un agrégat produit une valeur unique calculée pour toutes les lignes sélectionnées). Quand GROUP BY est présent, les expressions du SELECT ne peuvent faire référence qu'à des colonnes groupées, sauf à l'intérieur de fonctions d'agrégat, ou bien si la colonne non groupée dépend fonctionnellement des colonnes groupées. En effet, s'il en était autrement, il y aurait plus d'une valeur possible pour la colonne non groupée. Une dépendance fonctionnelle existe si les colonnes groupées (ou un sous-ensemble de ces derniÚres) sont la clé primaire de la table contenant les colonnes non groupées.

Clause HAVING

La clause optionnelle HAVING a la forme générale

HAVING condition

oĂč condition est identique Ă  celle spĂ©cifiĂ©e pour la clause WHERE.

HAVING Ă©limine les lignes groupĂ©es qui ne satisfont pas Ă  la condition. HAVING est diffĂ©rent de WHERE : WHERE filtre les lignes individuelles avant l'application de GROUP BY alors que HAVING filtre les lignes groupĂ©es créées par GROUP BY. Chaque colonne rĂ©fĂ©rencĂ©e dans condition doit faire rĂ©fĂ©rence sans ambiguĂŻtĂ© Ă  une colonne groupĂ©e, sauf si la rĂ©fĂ©rence apparaĂźt dans une fonction d'agrĂ©gat.

MĂȘme en l'absence de clause GROUP BY, la prĂ©sence de HAVING transforme une requĂȘte en requĂȘte groupĂ©e. Cela correspond au comportement d'une requĂȘte contenant des fonctions d'agrĂ©gats mais pas de clause GROUP BY. Les lignes sĂ©lectionnĂ©es ne forment qu'un groupe, la liste du SELECT et la clause HAVING ne peuvent donc faire rĂ©fĂ©rence qu'Ă  des colonnes Ă  l'intĂ©rieur de fonctions d'agrĂ©gats. Une telle requĂȘte ne produira qu'une seule ligne si la condition HAVING est rĂ©alisĂ©e, aucune dans le cas contraire.

Clause WINDOW

La clause optionnelle WINDOW a la forme générale

WINDOW nom_window AS ( définition_window ) [, ...]

oĂč nom_window est un nom qui peut ĂȘtre rĂ©fĂ©rencĂ© par des clauses OVER ou des dĂ©finitions de window, et dĂ©finition_window est

[ nom_window_existante ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operateur ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ clause_frame ]

Si un nom_window_existante est spĂ©cifiĂ©, il doit se rĂ©fĂ©rer Ă  une entrĂ©e prĂ©cĂ©dente dans la liste WINDOW ; la nouvelle Window copie sa clause de partitionnement de cette entrĂ©e, ainsi que sa clause de tri s'il y en a. Dans ce cas, la nouvelle Window ne peut pas spĂ©cifier sa propre clause PARTITION BY, et ne peut spĂ©cifier de ORDER BY que si la Window copiĂ©e n'en a pas. La nouvelle Window utilise toujours sa propre clause frame ; la Window copiĂ©e ne doit pas possĂ©der de clause frame.

Les Ă©lĂ©ments de la liste PARTITION BY sont interprĂ©tĂ©s Ă  peu prĂšs de la mĂȘme façon que des Ă©lĂ©ments de la section intitulĂ©e « Clause GROUP BY Â», sauf qu'ils sont toujours des expressions simples et jamais le nom ou le numĂ©ro d'une colonne en sortie. Une autre diffĂ©rence est que ces expressions peuvent contenir des appels Ă  des fonctions d' agrĂ©gat, ce qui n'est pas autorisĂ© dans une clause GROUP BY classique. Ceci est autorisĂ© ici parce que le windowing se produit aprĂšs le regroupement et l' agrĂ©gation.

De façon similaire, les Ă©lĂ©ments de la liste ORDER BY sont interprĂ©tĂ©s Ă  peu prĂšs de la mĂȘme façon que les Ă©lĂ©ments d'un la section intitulĂ©e « Clause ORDER BY Â», sauf que les expressions sont toujours prises comme de simples expressions et jamais comme le nom ou le numĂ©ro d'une colonne en sortie.

La clause clause_frame optionnelle dĂ©finit la frame window pour les fonctions window qui dĂ©pendent de la frame (ce n'est pas le cas de toutes). La frame window est un ensemble de lignes liĂ©es Ă  chaque ligne de la requĂȘte (appelĂ©e la ligne courante). La clause_frame peut ĂȘtre une des clauses suivantes :

{ RANGE | ROWS } début_frame
{ RANGE | ROWS } BETWEEN début_frame AND fin_frame

oĂč dĂ©but_frame et fin_frame peuvent valoir

UNBOUNDED PRECEDING
valeur PRECEDING
CURRENT ROW
valeur FOLLOWING
UNBOUNDED FOLLOWING

Si fin_frame n'est pas prĂ©cisĂ©, il vaut par dĂ©faut CURRENT ROW. Les restrictions sont les suivantes : dĂ©but_frame ne peut pas valoir UNBOUNDED FOLLOWING, fin_frame ne peut pas valoir UNBOUNDED PRECEDING, et le choix fin_frame ne peut apparaĂźtre avant le choix dĂ©but_frame -- par exemple RANGE BETWEEN CURRENT ROW AND valeur PRECEDING n'est pas permis.

L'option par dĂ©faut pour la clause frame est RANGE UNBOUNDED PRECEDING, ce qui revient au mĂȘme que RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ; il positionne la frame pour qu'il couvre toutes les lignes Ă  partir du dĂ©but de la partition jusqu'Ă  la derniĂšre ligne Ă  Ă©galitĂ© avec la ligne courante dans l'ordre dĂ©fini par l' ORDER BY (ce qui signifie toutes les lignes s'il n'y a pas d' ORDER BY). GĂ©nĂ©ralement, UNBOUNDED PRECEDING signifie que la frame commence Ă  la premiĂšre ligne de la partition, et de mĂȘme UNBOUNDED FOLLOWING signifie que la frame se termine avec la derniĂšre ligne de la partition (quel que soit le mode, RANGE ou bien ROWS ). Dans le mode ROWS, CURRENT ROW signifie que la frame commence ou se termine sur la ligne courante  ; mais dans le mode RANGE cela signifie que la frame dĂ©bute ou se termine sur la premiĂšre ou la derniĂšre des lignes Ă  Ă©galitĂ© avec la ligne courante dans l'ordre de la clause ORDER BY. Les valeur PRECEDING et valeur FOLLOWING sont actuellement seulement permis en mode ROWS. Ils indiquent que la frame dĂ©bute ou se termine autant de lignes avant ou aprĂšs la ligne courante. valeur doit ĂȘtre une expression entiĂšre, ne contenant aucune variable, fonction d' agrĂ©gat ni fonction window. La valeur ne doit ĂȘtre ni null ni nĂ©gative  ; mais elle peut ĂȘtre de zĂ©ro, ce qui sĂ©lectionne la ligne courante elle-mĂȘme.

Attention, les options ROWS peuvent produire des rĂ©sultats imprĂ©visibles si l'ordre dĂ©fini par l' ORDER BY n'ordonne pas les lignes de maniĂšre unique. Les options RANGE sont conçues pour s'assurer que les lignes qui sont Ă  Ă©galitĂ© suivant l'ordre de l' ORDER BY sont traitĂ©es de la mĂȘme maniĂšre  ; toutes les lignes Ă  Ă©galitĂ© seront ensemble dans la frame ou ensemble hors de la frame.

L'utilitĂ© d'une clause WINDOW est de spĂ©cifier le comportement des fonctions window apparaissant dans la clause la section intitulĂ©e « Liste SELECT Â» ou la clause la section intitulĂ©e « Clause ORDER BY Â» de la requĂȘte. Ces fonctions peuvent rĂ©fĂ©rencer les entrĂ©es de clauses WINDOW par nom dans leurs clauses OVER. Toutefois, il n'est pas obligatoire qu'une entrĂ©e de clause WINDOW soit rĂ©fĂ©rencĂ©e quelque part ; si elle n'est pas utilisĂ©e dans la requĂȘte, elle est simplement ignorĂ©e. Il est possible d'utiliser des fonctions window sans aucune clause WINDOW puisqu'une fonction window peut spĂ©cifier sa propre dĂ©finition de window directement dans sa clause OVER. Toutefois, la clause WINDOW Ă©conomise de la saisie quand la mĂȘme dĂ©finition window est utilisĂ©e pour plus d'une fonction window.

Les fonctions window sont dĂ©crites en dĂ©tail dans Section 3.5, « Fonctions de fenĂȘtrage Â», Section 4.2.8, « Appels de fonction de fenĂȘtrage Â» et Section 7.2.4, « Traitement de fonctions Window Â».

Liste SELECT

La liste SELECT (entre les mots clés SELECT et FROM) spécifie les expressions qui forment les lignes en sortie de l'instruction SELECT. Il se peut que les expressions fassent référence aux colonnes traitées dans la clause FROM. En fait, en général, elles le font.

Comme pour une table, chaque colonne de sortie d'un SELECT a un nom. Dans un SELECT simple, ce nom est juste utilisĂ© pour donner un titre Ă  la colonne pour l'affichage, mais quand le SELECT est une sous-requĂȘte d'une requĂȘte plus grande, le nom est vu par la grande requĂȘte comme le nom de colonne de la table virtuelle produite par la sous-requĂȘte. Pour indiquer le nom Ă  utiliser pour une colonne de sortie, Ă©crivez AS nom_de_sortie aprĂšs l'expression de la colonne. (Vous pouvez omettre AS seulement si le nom de colonne souhaitĂ© n'est pas un mot clĂ© rĂ©servĂ© par PostgreSQLℱ (voir Annexe C, Mots-clĂ© SQL). Pour vous protĂ©ger contre l'ajout futur d'un mot clĂ©, il est recommandĂ© que vous Ă©criviez toujours AS ou que vous mettiez le nom de sortie entre guillemets. Si vous n'indiquez pas de nom de colonne, un nom est choisi automatiquement par PostgreSQLℱ. Si l'expression de la colonne est une simple rĂ©fĂ©rence Ă  une colonne alors le nom choisi est le mĂȘme que le nom de la colonne. Dans les cas plus complexes, un nom de fonction ou de type peut ĂȘtre utilisĂ©, ou le systĂšme peut opter pour un nom gĂ©nĂ©rĂ© automatiquement tel que ?column?.

Un nom de colonne de sortie peut ĂȘtre utilisĂ© pour se rĂ©fĂ©rer Ă  la valeur de la colonne dans les clauses ORDER BY et GROUP BY, mais pas dans la clauseWHERE ou HAVING ; Ă  cet endroit, vous devez Ă©crire l'expression.

* peut ĂȘtre utilisĂ©, Ă  la place d'une expression, dans la liste de sortie comme raccourci pour toutes les colonnes des lignes sĂ©lectionnĂ©es. De plus, nom_table.* peut ĂȘtre Ă©crit comme raccourci pour toutes les colonnes de cette table. Dans ces cas, il est impossible de spĂ©cifier de nouveaux noms avec AS ; les noms des colonnes de sorties seront les mĂȘme que ceux de la table.

DISTINCT Clause

Si SELECT DISTINCT est spécifié, toutes les lignes en double sont supprimées de l'ensemble de résultats (une ligne est conservée pour chaque groupe de doublons). SELECT ALL spécifie le contraire : toutes les lignes sont conservées. C'est l'option par défaut.

SELECT DISTINCT ON ( expression [, ...] ) conserve seulement la premiĂšre ligne de chaque ensemble de lignes pour lesquelles le rĂ©sultat de l'expression est identique. Les expressions DISTINCT ON expressions sont interprĂ©tĂ©es avec les mĂȘmes rĂšgles que pour ORDER BY (voir ci-dessous). Notez que la « premiĂšre ligne Â» de chaque ensemble est imprĂ©visible, Ă  moins que la clause ORDER BY ne soit utilisĂ©e, assurant ainsi que la ligne souhaitĂ©e apparaisse en premier. Par exemple :

SELECT DISTINCT ON (lieu) lieu, heure, rapport
    FROM rapport_météo
    ORDER BY lieu, heure DESC;

renvoie le rapport météo le plus récent de chaque endroit. Mais si nous n'avions pas utilisé ORDER BY afin de forcer le tri du temps dans le sens descendant des temps pour chaque endroit, nous aurions récupéré, pour chaque lieu, n'importe quel bulletin de ce lieu.

La (ou les ) expression(s) DISTINCT ON doivent correspondre à l'expression (ou aux expressions) ORDER BY la(les) plus à gauche. La clause ORDER BY contient habituellement des expressions supplémentaires qui déterminent l'ordre des lignes au sein de chaque groupe DISTINCT ON.

Clause UNION

La clause UNION a la forme gĂ©nĂ©rale :

instruction_select UNION [ ALL | DISTINCT ] instruction_select

instruction_select est une instruction SELECT sans clause ORDER BY, LIMIT, FOR SHARE ou FOR UPDATE. (ORDER BY et LIMIT peuvent ĂȘtre attachĂ©s Ă  une sous-expression si elle est entourĂ©e de parenthĂšses. Sans parenthĂšses, ces clauses s'appliquent au rĂ©sultat de l'UNION, non Ă  l'expression Ă  sa droite.)

L'opĂ©rateur UNION calcule l'union ensembliste des lignes renvoyĂ©es par les instructions SELECT impliquĂ©es. Une ligne est dans l'union de deux ensembles de rĂ©sultats si elle apparaĂźt dans au moins un des ensembles. Les deux instructions SELECT qui reprĂ©sentent les opĂ©randes directes de l'UNION doivent produire le mĂȘme nombre de colonnes et les colonnes correspondantes doivent ĂȘtre d'un type de donnĂ©es compatible.

Sauf lorsque l'option ALL est spĂ©cifiĂ©e, il n'y a pas de doublons dans le rĂ©sultat de UNION. ALL empĂȘche l'Ă©limination des lignes dupliquĂ©es. UNION ALL est donc significativement plus rapide qu'UNION, et sera prĂ©fĂ©rĂ©. DISTINCT peut Ă©ventuellement ĂȘtre ajoutĂ© pour prĂ©ciser explicitement le comportement par dĂ©faut : l'Ă©limination des lignes en double.

Si une instruction SELECT contient plusieurs opérateurs UNION, ils sont évalués de gauche à droite, sauf si l'utilisation de parenthÚses impose un comportement différent.

Actuellement, FOR UPDATE et FOR SHARE ne peuvent pas ĂȘtre spĂ©cifiĂ©s pour un rĂ©sultat d'UNION ou pour toute entrĂ©e d'un UNION.

Clause INTERSECT

La clause INTERSECT a la forme gĂ©nĂ©rale :

instruction_select INTERSECT [ ALL | DISTINCT ] instruction_select

instruction_select est une instruction SELECT sans clause ORDER BY, LIMIT, FOR UPDATE ou FOR SHARE.

L'opérateur INTERSECT calcule l'intersection des lignes renvoyées par les instructions SELECT impliquées. Une ligne est dans l'intersection des deux ensembles de résultats si elle apparaßt dans chacun des deux ensembles.

Le rĂ©sultat d'INTERSECT ne contient aucune ligne dupliquĂ©e sauf si l'option ALL est spĂ©cifiĂ©e. Dans ce cas, une ligne dupliquĂ©e m fois dans la table gauche et n fois dans la table droite apparaĂźt min(m,n) fois dans l'ensemble de rĂ©sultats. DISTINCT peut Ă©ventuellement ĂȘtre ajoutĂ© pour prĂ©ciser explicitement le comportement par dĂ©faut : l'Ă©limination des lignes en double.

Si une instruction SELECT contient plusieurs opérateurs INTERSECT, ils sont évalués de gauche à droite, sauf si l'utilisation de parenthÚses impose un comportement différent. INTERSECT a une priorité supérieur à celle d'UNION. C'est-à-dire que A UNION B INTERSECT C est lu comme A UNION (B INTERSECT C).

Actuellement, FOR UPDATE et FOR SHARE ne peuvent pas ĂȘtre spĂ©cifiĂ©s pour un rĂ©sultat d'INTERSECT ou pour une entrĂ©e d'INTERSECT.

Clause EXCEPT

La clause EXCEPT a la forme gĂ©nĂ©rale :

instruction_select EXCEPT [ ALL | DISTINCT ] instruction_select

instruction_select est une instruction SELECT sans clause ORDER BY, LIMIT, FOR UPDATE ou FOR SHARE.

L'opérateur EXCEPT calcule l'ensemble de lignes qui appartiennent au résultat de l'instruction SELECT de gauche mais pas à celui de droite.

Le rĂ©sultat d'EXCEPT ne contient aucune ligne dupliquĂ©e sauf si l'option ALL est spĂ©cifiĂ©e. Dans ce cas, une ligne dupliquĂ©e m fois dans la table gauche et n fois dans la table droite apparaĂźt max(m-n,0) fois dans l'ensemble de rĂ©sultats. DISTINCT peut Ă©ventuellement ĂȘtre ajoutĂ© pour prĂ©ciser explicitement le comportement par dĂ©faut : l'Ă©limination des lignes en double.

Si une instruction SELECT contient plusieurs opĂ©rateurs EXCEPT, ils sont Ă©valuĂ©s de gauche Ă  droite, sauf si l'utilisation de parenthĂšses impose un comportement diffĂ©rent. EXCEPT a la mĂȘme prioritĂ© qu'UNION.

Actuellement, FOR UPDATE et FOR SHARE ne peuvent pas ĂȘtre spĂ©cifiĂ©s dans un rĂ©sultat EXCEPT ou pour une entrĂ©e d'un EXCEPT.

Clause ORDER BY

La clause optionnelle ORDER BY a la forme gĂ©nĂ©rale :

ORDER BY expression [ ASC | DESC | USING opérateur ] [ NULLS { FIRST | LAST } ] [, ...]

La clause ORDER BY impose le tri des lignes de résultat suivant les expressions spécifiées. Si deux lignes sont identiques suivant l'expression la plus à gauche, elles sont comparées avec l'expression suivante et ainsi de suite. Si elles sont identiques pour toutes les expressions de tri, elles sont renvoyées dans un ordre dépendant de l'implantation.

Chaque expression peut ĂȘtre le nom ou le numĂ©ro ordinal d'une colonne en sortie (Ă©lĂ©ment de la liste SELECT). Elle peut aussi ĂȘtre une expression arbitraire formĂ©e Ă  partir de valeurs des colonnes.

Le numéro ordinal fait référence à la position ordinale (de gauche à droite) de la colonne de résultat. Cette fonctionnalité permet de définir un ordre sur la base d'une colonne dont le nom n'est pas unique. Ce n'est pas particuliÚrement nécessaire parce qu'il est toujours possible d'affecter un nom à une colonne de résultat avec la clause AS.

Il est aussi possible d'utiliser des expressions quelconques dans la clause ORDER BY, ce qui inclut des colonnes qui n'apparaissent pas dans la liste rĂ©sultat du SELECT. Ainsi, l'instruction suivante est valide :

                SELECT nom FROM distributeurs ORDER BY code;

Il y a toutefois une limitation à cette fonctionnalité. La clause ORDER BY qui s'applique au résultat d'une clause UNION, INTERSECT ou EXCEPT ne peut spécifier qu'un nom ou numéro de colonne en sortie, pas une expression.

Si une expression ORDER BY est un nom qui correspond Ă  la fois Ă  celui d'une colonne rĂ©sultat et Ă  celui d'une colonne en entrĂ©e, ORDER BY l'interprĂšte comme le nom de la colonne rĂ©sultat. Ce comportement est Ă  l'opposĂ© de celui de GROUP BY dans la mĂȘme situation. Cette incohĂ©rence est imposĂ©e par la compatibilitĂ© avec le standard SQL.

Un mot clĂ© ASC (ascendant) ou DESC (descendant) peut ĂȘtre ajoutĂ© aprĂšs toute expression de la clause ORDER BY. ASC est la valeur utilisĂ©e par dĂ©faut. Un nom d'opĂ©rateur d'ordre spĂ©cifique peut Ă©galement ĂȘtre fourni dans la clause USING. Un opĂ©rateur de tri doit ĂȘtre un membre plus-petit-que ou plus-grand-que de certaines familles d'opĂ©rateur B-tree. ASC est habituellement Ă©quivalent Ă  USING < et DESC Ă  USING >. Le crĂ©ateur d'un type de donnĂ©es utilisateur peut dĂ©finir Ă  sa guise le tri par dĂ©faut qui peut alors correspondre Ă  des opĂ©rateurs de nom diffĂ©rent.

Si NULLS LAST est indiquĂ©, les valeurs NULL sont listĂ©es aprĂšs toutes les valeurs non NULL  si NULLS FIRST est indiquĂ©, les valeurs NULL apparaissent avant toutes les valeurs non NULL. Si aucune des deux n'est prĂ©sente, le comportement par dĂ©faut est NULLS LAST quand ASC est utilisĂ© (de façon explicite ou non) et NULLS FIRST quand DESC est utilisĂ© (donc la valeur par dĂ©faut est d'agir comme si les NULL Ă©taient plus grands que les non NULL). Quand USING est indiquĂ©, le tri des NULL par dĂ©faut dĂ©pend du fait que l'opĂ©rateur est un plus-petit-que ou un plus-grand-que.

Notez que les options de tri s'appliquent seulement Ă  l'expression qu'elles suivent. Par exemple, ORDER BY x, y DESC ne signifie pas la mĂȘme chose que ORDER BY x DESC, y DESC.

Les chaĂźnes de caractĂšres sont triĂ©es suivant le collationnement qui s'applique Ă  la colonne triĂ©e. Ce collationnement est surchargeable si nĂ©cessaire en ajoutant une clause COLLATE dans l'expression, par exemple ORDER BY mycolumn COLLATE "en_US". Pour plus d'informations, voir Section 4.2.10, « Expressions de collationnement Â» et Section 22.2, « Support des collations Â».

Clause LIMIT

La clause LIMIT est constituĂ©e de deux sous-clauses indĂ©pendantes :

LIMIT { nombre | ALL }
OFFSET début

nombre spécifie le nombre maximum de lignes à renvoyer alors que début spécifie le nombre de lignes à passer avant de commencer à renvoyer des lignes. Lorsque les deux clauses sont spécifiées, début lignes sont passées avant de commencer à compter les nombre lignes à renvoyer.

Si l'expression de compte est évaluée à NULL, il est traité comme LIMIT ALL, c'est-à-dire sans limite. Si début est évalué à NULL, il est traité comme OFFSET 0.

SQL:2008 a introduit une sytaxe diffĂ©rente pour obtenir le mĂȘme rĂ©sultat. PostgreSQLℱ supporte aussi cette syntaxe.

OFFSET début { ROW | ROWS }
FETCH { FIRST | NEXT } [ compte ] { ROW | ROWS } ONLY

Avec cette syntaxe, pour Ă©crire tout sauf une simple constant de type entier pour dĂ©but ou compte, vous devez l'entourer de parenthĂšses. Si compte est omis dans une clause FETCH, il vaut 1 par dĂ©faut. ROW et ROWS ainsi que FIRST et NEXT sont des mots qui n'influencent pas les effets de ces clauses. D'aprĂšs le standard, la clause OFFSET doit venir avant la clause FETCH si les deux sont prĂ©sentes ; PostgreSQLℱ est plus laxiste et autorise un ordre diffĂ©rent.

Avec LIMIT, utiliser la clause ORDER BY permet de contraindre l'ordre des lignes de résultat. Dans le cas contraire, le sous-ensemble obtenu n'est pas prévisible -- rien ne permet de savoir à quel ordre correspondent les lignes retournées. Celui-ci ne sera pas connu tant qu'ORDER BY n'aura pas été précisé.

Lors de la gĂ©nĂ©ration d'un plan de requĂȘte, le planificateur tient compte de LIMIT. Le risque est donc grand d'obtenir des plans qui diffĂšrent (ordres des lignes diffĂ©rents) suivant les valeurs utilisĂ©es pour LIMIT et OFFSET. Ainsi, sĂ©lectionner des sous-ensembles diffĂ©rents d'un rĂ©sultat Ă  partir de valeurs diffĂ©rentes de LIMIT/OFFSET aboutit Ă  des rĂ©sultats incohĂ©rents Ă  moins d'avoir figĂ© l'ordre des lignes Ă  l'aide de la clause ORDER BY. Ce n'est pas un bogue, mais une consĂ©quence du fait que SQL n'assure pas l'ordre de prĂ©sentation des rĂ©sultats sans utilisation d'une clause ORDER BY.

Il est mĂȘme possible pour des exĂ©cutions rĂ©pĂ©tĂ©es de la mĂȘme requĂȘte LIMIT de renvoyer diffĂ©rents sous-ensembles des lignes d'une table s'il n'y a pas de clause ORDER BY pour forcer la sĂ©lection d'un sous-ensemble dĂ©terministe. Encore une fois, ce n'est pas un bogue ; le dĂ©terminisme des rĂ©sultats n'est tout simplement pas garanti dans un tel cas.

Clause FOR UPDATE/FOR SHARE

La clause FOR UPDATE a la forme :

FOR UPDATE [ OF nom_table [, ...] ] [ NOWAIT ]

La clause liĂ©e, FOR SHARE, a la forme :

FOR SHARE [ OF nom_table [, ...] ] [ NOWAIT ]

FOR UPDATE verrouille pour modification les lignes rĂ©cupĂ©rĂ©es par l'instruction SELECT. Cela les empĂȘche d'ĂȘtre modifiĂ©es ou supprimĂ©es par les autres transactions jusqu'Ă  la fin de la transaction en cours. Les autres transactions qui tentent des UPDATE, DELETE ou SELECT FOR UPDATE sur ces lignes sont bloquĂ©es jusqu'Ă  la fin de la transaction courante. De plus, si un UPDATE, DELETE ou SELECT FOR UPDATE a dĂ©jĂ  verrouillĂ© une ligne ou un ensemble de lignes Ă  partir d'une autre transaction, SELECT FOR UPDATE attend la fin de l'autre transaction puis verrouille et renvoie la ligne modifiĂ©e (ou aucune ligne si elle a Ă©tĂ© supprimĂ©e). Cependant, au sein d'une transaction REPEATABLE READ ou SERIALIZABLE, une erreur est levĂ©e si une ligne Ă  verrouiller Ă  changĂ© depuis le dĂ©but de la transaction. Pour plus d'informations, voir Chapitre 13, ContrĂŽle d'accĂšs simultanĂ©.

FOR SHARE a un comportement similaire. La différence se situe dans le type de verrou acquis. Contrairement à FOR UPDATE qui pose un verrou exclusif, FOR SHARE pose un verrou partagé sur chaque ligne récupérée. Un verrou partagée bloque les instructions UPDATE, DELETE ou SELECT FOR UPDATE des transaction concurrentes accédant à ces lignes, mais il n'interdit pas les SELECT FOR SHARE.

Pour Ă©viter Ă  l'opĂ©ration d'attendre la validation des autres transactions, on utilise l'option NOWAIT. SELECT FOR UPDATE NOWAIT rapporte une erreur si une ligne sĂ©lectionnĂ©e ne peut pas ĂȘtre verrouillĂ©e immĂ©diatement. Il n'y a pas d'attente. NOWAIT s'applique seulement au(x) verrou(x) niveau ligne -- le verrou niveau table ROW SHARE est toujours pris de façon ordinaire (voir Chapitre 13, ContrĂŽle d'accĂšs simultanĂ©). L'option NOWAIT de LOCK(7) peut toujours ĂȘtre utilisĂ©e pour acquĂ©rir le verrou niveau table sans attendre.

Si des tables particuliĂšres sont nommĂ©es dans les clauses FOR UPDATE et FOR SHARE, alors seules les lignes provenant de ces tables sont verrouillĂ©es ; toute autre table utilisĂ©e dans le SELECT est simplement lue. Une clause FOR UPDATE ou FOR SHARE sans liste de tables affecte toute les tables utilisĂ©es dans l'instruction. Si FOR UPDATE ou FOR SHARE est appliquĂ©e Ă  une vue ou Ă  une sous-requĂȘte, cela affecte toutes les tables utilisĂ©es dans la vue ou la sous-requĂȘte. NĂ©anmoins, FOR UPDATE/FOR SHARE ne s'appliquent pas aux requĂȘtes WITH rĂ©fĂ©rencĂ©es par la clĂ© primaire. Si vous voulez qu'un verrouillage de lignes intervienne dans une requĂȘte WITH, spĂ©cifiez FOR UPDATE ou FOR SHARE Ă  l'intĂ©rieur de la requĂȘte WITH.

Plusieurs clauses FOR UPDATE et FOR SHARE peuvent ĂȘtre donnĂ©es si il est nĂ©cessaire de spĂ©cifier diffĂ©rents comportements de verrouillage pour diffĂ©rentes tables. Si la mĂȘme table est mentionnĂ© (ou affectĂ©e implicitement) par les clauses FOR UPDATE et FOR SHARE, alors elle est traitĂ©e comme un simple FOR UPDATE. De façon similaire, une table est traitĂ©e avec NOWAIT si c'est spĂ©cifiĂ©e sur au moins une des clauses qui l'affectent.

FOR UPDATE et FOR SHARE nĂ©cessitent que chaque ligne retournĂ©e soit clairement identifiable par une ligne individuelle d'une table ; ces options ne peuvent, par exemple, pas ĂȘtre utilisĂ©es avec des fonctions d'agrĂ©gats.

Quand FOR UPDATE ou FOR SHARE apparaissent au niveau le plus Ă©levĂ© d'une requĂȘte SELECT, les lignes verrouillĂ©es sont exactement celles qui sont renvoyĂ©es par la requĂȘte ; dans le cas d'une requĂȘte avec jointure, les lignes verrouillĂ©es sont celles qui contribuent aux lignes jointes renvoyĂ©es. De plus, les lignes qui ont satisfait aux conditions de la requĂȘte au moment de la prise de son instantanĂ© sont verrouillĂ©es, bien qu'elles ne seront pas retournĂ©es si elles ont Ă©tĂ© modifiĂ©es aprĂšs la prise du snapshot et ne satisfont plus les conditions de la requĂȘte. Si LIMIT est utilisĂ©, le verrouillage cesse une fois que suffisamment de lignes ont Ă©tĂ© renvoyĂ©es pour satisfaire la limite (mais notez que les lignes ignorĂ©es Ă  cause de la clause OFFSET seront verrouillĂ©es). De la mĂȘme maniĂšre, si FOR UPDATE ou FOR SHARE est utilisĂ© pour la requĂȘte d'un curseur, seules les lignes rĂ©ellement rĂ©cupĂ©rĂ©es ou parcourues par le curseur seront verrouillĂ©es.

Si FOR UPDATE ou FOR SHARE apparaissent dans un sous-SELECT, les lignes verrouillĂ©es sont celles renvoyĂ©es par la sous-requĂȘte Ă  la requĂȘte externe. Cela peut concerner moins de lignes que l'Ă©tude de la sous-requĂȘte seule pourrait faire penser, parce que les conditions de la requĂȘte externe peuvent ĂȘtre utilisĂ©es pour optimiser l'exĂ©cution de la sous-requĂȘte. Par exemple,

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5;

verrouillera uniquement le lignes pour lesquelles col1 = 5, mĂȘme si cette condition n'est pas Ă©crite dans la sous-requĂȘte.

[Attention]

Attention

Évitez de verrouiller une ligne puis de la modifier aprĂšs un nouveau point de sauvegarde ou aprĂšs un bloc d'exception PL/pgSQL. L'annulation suivante pourrait causer la perte du verrou. Par exemple :

BEGIN;
SELECT * FROM ma_table WHERE cle = 1 FOR UPDATE;
SAVEPOINT s;
UPDATE ma_table SET ... WHERE cle = 1;
ROLLBACK TO s;

AprĂšs le ROLLBACK, la ligne est rĂ©ellement dĂ©verrouillĂ©e au lieu de retourner Ă  son Ă©tat avant le point de sauvegarde. Ceci peut arriver si une ligne verrouillĂ©e dans la transaction en cours est mise Ă  jour ou supprimĂ©e, ou si un verrou partagĂ© est passĂ© en verrou exclusif : dans tous ces cas, l'Ă©tat prĂ©cĂ©dent du verrou est oubliĂ©. Si la transaction est ensuite annulĂ©e Ă  un Ă©tat entre la commande de verrou initiale et la modification qui a suivi, la ligne n'apparaĂźtra plus verrouillĂ©e. Ceci est une dĂ©ficience de l'implĂ©mentation qui sera corrigĂ©e dans une prochaine version de PostgreSQLℱ.

[Attention]

Attention

Il est possible qu'une commande SELECT exĂ©cutĂ©e au niveau d'isolation READ COMMITTED et utilisant ORDER BY et FOR UPDATE/SHARE renvoie les lignes dans le dĂ©sordre. C'est possible car l' ORDER BY est appliquĂ© en premier. La commande trie le rĂ©sultat, mais peut alors ĂȘtre bloquĂ©e le temps d'obtenir un verrou sur une ou plusieurs des lignes. Une fois que le SELECT est dĂ©bloquĂ©, des valeurs sur la colonne qui sert Ă  ordonner peuvent avoir Ă©tĂ© modifiĂ©es, ce qui entraĂźne ces lignes apparaissant dans le dĂ©sordre (bien qu'elles soient dans l'ordre par rapport aux valeurs d'origine de ces colonnes). Ceci peut ĂȘtre contournĂ© si besoin en plaçant la clause FOR UPDATE/SHARE dans une sous-requĂȘte, par exemple

SELECT * FROM (SELECT * FROM matable FOR UPDATE) ss ORDER BY column1;

Notez que cela entraßne le verrouillage de toutes les lignes de matable, alors que FOR UPDATE au niveau supérieur verrouillerait seulement les lignes réellement renvoyées. Cela peut causer une différence de performance significative, en particulier si l' ORDER BY est combiné avec LIMIT ou d'autres restrictions. Cette technique est donc recommandée uniquement si vous vous attendez à des mises à jour concurrentes sur les colonnes servant à l'ordonnancement et qu'un résultat strictement ordonné est requis.

Au niveau d'isolation de transactions REPEATABLE READ et SERIALIZABLE, cela causera une erreur de sérialisation (avec un SQLSTATE valant '40001'), donc il n'est pas possible de recevoir des lignes non triées avec ces niveaux d'isolation.

Commande TABLE

La commande

TABLE nom

est complÚtement équivalente à

SELECT * FROM nom

Elle peut ĂȘtre utilisĂ©e comme commande principale d'une requĂȘte, ou bien comme une variante syntaxique permettant de gagner de la place dans des parties de requĂȘtes complexes.

Exemples

Joindre la table films avec la table distributeurs :

              SELECT f.titre, f.did, d.nom, f.date_prod, f.genre
    FROM distributeurs d, films f
    WHERE f.did = d.did

       titre       | did |     nom      | date_prod  |   genre
-------------------+-----+--------------+------------+------------
 The Third Man     | 101 | British Lion | 1949-12-23 | Drame
 The African Queen | 101 | British Lion | 1951-08-11 | Romantique
 ...

Additionner la colonne longueur de tous les films, grouper les rĂ©sultats par genre :

              SELECT genre, sum(longueur) AS total FROM films GROUP BY genre;

   genre    | total
------------+-------
 Action     | 07:34
 Comédie    | 02:58
 Drame      | 14:28
 Musical    | 06:42
 Romantique | 04:38

Additionner la colonne longueur de tous les films, grouper les rĂ©sultats par genre et afficher les groupes dont les totaux font moins de cinq heures :

              SELECT genre, sum(longueur) AS total
    FROM films
    GROUP BY genre
    HAVING sum(longueur) < interval '5 hours';

   genre    | total
------------+-------
 Comedie    | 02:58
 Romantique | 04:38

Les deux exemples suivants reprĂ©sentent des façons identiques de trier les rĂ©sultats individuels en fonction du contenu de la deuxiĂšme colonne (nom) :

              SELECT * FROM distributeurs ORDER BY nom;
SELECT * FROM distributeurs ORDER BY 2;

 did |       nom
-----+------------------
 109 | 20th Century Fox
 110 | Bavaria Atelier
 101 | British Lion
 107 | Columbia
 102 | Jean Luc Godard
 113 | Luso films
 104 | Mosfilm
 103 | Paramount
 106 | Toho
 105 | United Artists
 111 | Walt Disney
 112 | Warner Bros.
 108 | Westward

L'exemple suivant présente l'union des tables distributeurs et acteurs, restreignant les résultats à ceux de chaque table dont la premiÚre lettre est un W. Le mot clé ALL est omis, ce qui permet de n'afficher que les lignes distinctes.

              distributeurs:               acteurs:
 did |     nom               id |     nom
-----+--------------        ----+----------------
 108 | Westward               1 | Woody Allen
 111 | Walt Disney            2 | Warren Beatty
 112 | Warner Bros.           3 | Walter Matthau
 ...                         ...

SELECT distributeurs.nom
    FROM distributeurs
    WHERE distributeurs.nom LIKE 'W%'
UNION
SELECT actors.nom
    FROM acteurs
    WHERE acteurs.nom LIKE 'W%';

      nom
----------------
 Walt Disney
 Walter Matthau
 Warner Bros.
 Warren Beatty
 Westward
 Woody Allen

L'exemple suivant prĂ©sente l'utilisation d'une fonction dans la clause FROM, avec et sans liste de dĂ©finition de colonnes :

              CREATE FUNCTION distributeurs(int) RETURNS SETOF distributeurs AS $$
    SELECT * FROM distributeurs WHERE did = $1;
$$ LANGUAGE SQL;

SELECT * FROM distributeurs(111);
 did |    name
-----+-------------
 111 | Walt Disney

CREATE FUNCTION distributeurs_2(int) RETURNS SETOF record AS $$
    SELECT * FROM distributeurs WHERE did = $1;
$$ LANGUAGE SQL;

SELECT * FROM distributeurs_2(111) AS (f1 int, f2 text);
 f1  |     f2
-----+-------------
 111 | Walt Disney

Cet exemple montre comment utiliser une clause WITH simple:

WITH t AS (
    SELECT random() as x FROM generate_series(1, 3)
  )
SELECT * FROM t
UNION ALL
SELECT * FROM t

         x          
--------------------
  0.534150459803641
  0.520092216785997
 0.0735620250925422
  0.534150459803641
  0.520092216785997
 0.0735620250925422

Notez que la requĂȘte WITH n'a Ă©tĂ© Ă©valuĂ©e qu'une seule fois, ce qui fait qu'on a deux jeux contenant les mĂȘmes trois valeurs.

Cet exemple utilise WITH RECURSIVE pour trouver tous les subordonnĂ©s (directs ou indirects) de l'employĂ©e Marie, et leur niveau de subordination, Ă  partir d'une table qui ne donne que les subordonnĂ©s directs :

WITH RECURSIVE recursion_employes(distance, nom_employe, nom_manager) AS (
    SELECT 1, nom_employe, nom_manager
    FROM employe
    WHERE nom_manager = 'Marie'
  UNION ALL
    SELECT er.distance + 1, e.nom_employe, e.nom_manager
    FROM recursion_employes er, employe e
    WHERE er.nom_employe = e.nom_manager
  )
SELECT distance, nom_employe FROM recursion_employes;

Notez la forme typique des requĂȘtes rĂ©cursives : une condition initiale, suivie par UNION, suivis par la partie rĂ©cursive de la requĂȘte. Assurez-vous que la partie rĂ©cursive de la requĂȘte finira par ne plus retourner d'enregistrement, sinon la requĂȘte bouclera indĂ©finiment (Voir Section 7.8, « RequĂȘtes WITH (Common Table Expressions) Â» pour plus d'exemples).

Compatibilité

L'instruction SELECT est évidemment compatible avec le standard SQL. Mais il y a des extensions et quelques fonctionnalités manquantes.

Clauses FROM omises

PostgreSQLℱ autorise l'omission de la clause FROM. Cela permet par exemple de calculer le rĂ©sultat d'expressions simples :

SELECT 2+2;

 ?column?
----------
        4

D'autres bases de données SQL interdisent ce comportement, sauf à introduire une table virtuelle d'une seule ligne sur laquelle exécuter la commande SELECT.

S'il n'y a pas de clause FROM, la requĂȘte ne peut pas rĂ©fĂ©rencer les tables de la base de donnĂ©es. La requĂȘte suivante est, ainsi, invalide :

                SELECT distributors.* WHERE distributors.name = 'Westward';

Les versions antĂ©rieures Ă  PostgreSQLℱ 8.1 acceptaient les requĂȘtes de cette forme en ajoutant une entrĂ©e implicite Ă  la clause FROM pour chaque table rĂ©fĂ©rencĂ©e. Ce n'est plus autorisĂ©.

Omettre le mot clé AS

Dans le standard SQL, le mot clĂ© AS peut ĂȘtre omis devant une colonne de sortie Ă  partir du moment oĂč le nouveau nom de colonne est un nom valide de colonne (c'est-Ă -dire, diffĂ©rent d'un mot clĂ© rĂ©servĂ©). PostgreSQLℱ est lĂ©gĂšrement plus restrictif : AS est nĂ©cessaire si le nouveau nom de colonne est un mot clĂ© quel qu'il soit, rĂ©servĂ© ou non. Il est recommandĂ© d'utiliser AS ou des colonnes de sortie entourĂ©es de guillemets, pour Ă©viter tout risque de conflit en cas d'ajout futur de mot clĂ©.

Dans les Ă©lĂ©ments de FROM, le standard et PostgreSQLℱ permettent que AS soit omis avant un alias qui n'est pas un mot clĂ© rĂ©servĂ©. Mais c'est peu pratique pour les noms de colonnes, Ă  causes d'ambiguĂŻtĂ©s syntaxiques.

ONLY et l'héritage

Le standard SQL impose des parenthĂšses autour du nom de table aprĂšs la clause ONLY, comme dans SELECT * FROM ONLY (tab1), ONLY (tab2) WHERE .... PostgreSQLℱ considĂšre les parenthĂšses comme Ă©tant optionnelles.

PostgreSQLℱ autorise une * en fin pour indiquer explicitement le comportement opposĂ© de la clause ONLY (donc inclure les tables filles). Le standard ne le permet pas.

(Ces points s'appliquent de la mĂȘme façon Ă  toutes les commandes SQL supportant l'option ONLY.)

Espace logique disponible pour GROUP BY et ORDER BY

Dans le standard SQL-92, une clause ORDER BY ne peut utiliser que les noms ou numĂ©ros des colonnes en sortie, une clause GROUP BY que des expressions fondĂ©es sur les noms de colonnes en entrĂ©e. PostgreSQLℱ va plus loin, puisqu'il autorise chacune de ces clauses Ă  utiliser Ă©galement l'autre possibilitĂ©. En cas d'ambiguĂŻtĂ©, c'est l'interprĂ©tation du standard qui prĂ©vaut. PostgreSQLℱ autorise aussi l'utilisation d'expressions quelconques dans les deux clauses. Les noms apparaissant dans ces expressions sont toujours considĂ©rĂ©s comme nom de colonne en entrĂ©e, pas en tant que nom de colonne du rĂ©sultat.

SQL:1999 et suivant utilisent une dĂ©finition lĂ©gĂšrement diffĂ©rente, pas totalement compatible avec le SQL-92. NĂ©anmoins, dans la plupart des cas, PostgreSQLℱ interprĂšte une expression ORDER BY ou GROUP BY en suivant la norme SQL:1999.

Dépendances fonctionnelles

PostgreSQLℱ reconnaĂźt les dĂ©pendances fonctionnelles (qui permettent que les nom des colonnes ne soient pas dans le GROUP BY) seulement lorsqu'une clĂ© primaire est prĂ©sente dans la liste du GROUP BY. Le standard SQL spĂ©cifie des configurations supplĂ©mentaires qui doivent ĂȘtre reconnues.

Restrictions sur la clause WINDOW

Le standard SQL fournit des options additionnelles pour la clause_frame des window. PostgreSQLℱ ne supporte Ă  ce jour que les options mentionnĂ©es prĂ©cĂ©demment.

LIMIT et OFFSET

Les clauses LIMIT et OFFSET sont une syntaxe spĂ©cifique Ă  PostgreSQLℱ, aussi utilisĂ©e dans MySQLℱ. La norme SQL:2008 a introduit les clauses OFFSET ... FETCH {FIRST|NEXT}... pour la mĂȘme fonctionnalitĂ©, comme montrĂ© plus haut dans la section intitulĂ©e « Clause LIMIT Â». Cette syntaxe est aussi utilisĂ©e par IBM DB2ℱ. (Les applications Ă©crites pour Oracleℱ contournent frĂ©quemment le problĂšme par l'utilisation de la colonne auto-gĂ©nĂ©rĂ©e rownum pour obtenir les effets de ces clauses, qui n'est pas disponible sous PostgreSQL,)

FOR UPDATE and FOR SHARE

Bien que FOR UPDATE soit prĂ©sent dans le standard SQL, le standard ne l'autorise que comme une option de DECLARE CURSOR. PostgreSQLℱ l'autorise dans toute requĂȘte SELECT et dans toute sous-requĂȘte SELECT, mais c'est une extension. Ni la variante FOR SHARE, ni l'option NOWAIT n'apparaissent dans le standard.

Ordre de modification de données dans un WITH

PostgreSQLℱ permet que les clauses INSERT, UPDATE, et DELETE soient utilisĂ©es comme requĂȘtes WITH. Ceci n'est pas prĂ©sent dans le standard SQL.

Clauses non standard

La clause DISTINCT ON n'est pas définie dans le standard SQL.