SELECT, TABLE, WITH â rĂ©cupĂšre des lignes d'une table ou d'une vue
[ WITH [ RECURSIVE ]requĂȘte_with
[, ...] ] SELECT [ ALL | DISTINCT [ ON (expression
[, ...] ) ] ] [ { * |expression
[ [ AS ]nom_sortie
] } [, ...] ] [ FROMéléments_from
[, ...] ] [ WHEREcondition
] [ GROUP BYelement_regroupement
[, ...] ] [ HAVINGcondition
] [ WINDOWnom_window
AS (définition_window
) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ]select
] [ ORDER BYexpression
[ ASC | DESC | USINGopérateur
] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT {nombre
| ALL } ] [ OFFSETdébut
] [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [total
] { ROW | ROWS } ONLY ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OFnom_table
[, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ] avecéléments_from
qui peut ĂȘtre : [ ONLY ]nom_table
[ * ] [ [ AS ]alias
[ (alias_colonne
[, ...] ) ] ] [ TABLESAMPLEmethode_echantillonnage
(argument
[, ...] ) [ REPEATABLE (pourcentage_echantillon
) ] ] [ LATERAL ] (select
) [ AS ]alias
[ (alias_colonne
[, ...] ) ]nom_requĂȘte_with
[ [ AS ]alias
[ (alias_colonne
[, ...] ) ] ] [ LATERAL ]nom_fonction
( [argument
[, ...] ] ) [ WITH ORDINALITY ] [ [ AS ]alias
[ (alias_colonne
[, ...] ) ] ] [ LATERAL ]nom_fonction
( [argument
[, ...] ] ) [ AS ]alias
(définition_colonne
[, ...] ) [ LATERAL ]nom_fonction
( [argument
[, ...] ] ) AS (définition_colonne
[, ...] ) [ LATERAL ] ROWS FROM(nom_fonction
( [argument
[, ...] ] ) [ AS (définition_colonne
[, ...] ) ] [, ...] ) [ WITH ORDINALITY ] [ [ AS ]alias
[ (alias_colonne
[, ...] ) ] ]élément_from
type_jointure
élément_from
{ ONcondition_jointure
| USING (colonne_jointure
[, ...] ) }élément_from
NATURALtype_jointure
élément_from
élément_from
CROSS JOINélément_from
etelement_regroupement
peut valoir : ( )expression
(expression
[, ...] ) ROLLUP ( {expression
| (expression
[, ...] ) } [, ...] ) CUBE ( {expression
| (expression
[, ...] ) } [, ...] ) GROUPING SETS (element_regroupement
[, ...] ) etrequĂȘte_with
est :nom_requĂȘte_with
[ (nom_colonne
[, ...] ) ] AS [ [ NOT ] MATERIALIZED ] (select
|valeurs
|insert
|update
|delete
) TABLE [ ONLY ]nom_table
[ * ]
SELECT
récupÚre des lignes de zéro ou plusieurs
tables. Le traitement général de SELECT
est le
suivant :
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,
unless specified otherwise with NOT MATERIALIZED
(voir la section intitulée « Clause WITH
» ci-dessous).
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.)
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.)
Si la clause GROUP BY
est spécifiée or if there are
aggregate function calls, l'affichage est divisé en groupes de lignes qui
correspondent à une ou plusieurs valeurs, et aux résultats des fonctions
d'agrégat calculés.
Si la clause HAVING
est présente, elle élimine les
groupes qui ne satisfont pas la condition donnée. (Voir Clause GROUP BY
et
Clause HAVING
ci-dessous.)
Bien que les colonnes en sortie d'une requĂȘte sont calculĂ©es nominalement
Ă la prochaine Ă©tape, elles peuvent aussi ĂȘtre rĂ©fĂ©rencĂ©es (par nom ou
numéro) dans la clause GROUP BY
.
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.)
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.)
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.)
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.)
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.)
Si la clause FOR UPDATE
, FOR NO KEY UPDATE
,
FOR SHARE
ou FOR KEY 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 de verrouillage » 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 NO KEY UPDATE
,
FOR UPDATE
, FOR SHARE
ou
FOR KEY SHARE
requiert en plus le droit
UPDATE
(pour au moins une colonne de chaque table
sélectionnée).
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
, TABLE
, 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 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
.
La requĂȘte principale et les requĂȘtes WITH
sont toutes
exĂ©cutĂ©es en mĂȘme temps. Ceci implique que les effets d'une requĂȘte
modifiant des données dans la clause WITH
ne peuvent
pas ĂȘtre vus des autres parties de la requĂȘte, autrement qu'en lisant son
retour avec la clause RETURNING
. Si des telles
instructions de modification de donnĂ©es essaient de modifier la mĂȘme
ligne, les résultats sont inconnus.
Quand il y a plusieurs requĂȘtes dans la clause WITH
,
RECURSIVE
ne devra ĂȘtre Ă©crit qu'une seule fois,
immédiatement aprÚs WITH
. Cela s'applique Ă toutes les
requĂȘtes de la clause WITH
, bien que cela n'a pas
d'effet sur les requĂȘtes qui n'utilisent pas de rĂ©cursion de rĂ©fĂ©rence en
avant (forward references).
Une propriĂ©tĂ© clĂ© des requĂȘtes WITH
est qu'elles ne sont
normalement Ă©valuĂ©es qu'une seule fois par exĂ©cution de la requĂȘte principale,
mĂȘme si la 1requĂȘ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.
NĂ©anmoins, une requĂȘte WITH
peut ĂȘtre marquĂ©e
NOT MATERIALIZED
pour supprimer cette garantie. Dans ce
cas, la requĂȘte WITH
peut ĂȘtre intĂ©grĂ©e dans la requĂȘte
principale comme s'il s'agissait d'un simple
sous-SELECT
dans la clause FROM
de
la requĂȘte principale. Ceci rĂ©sulte en des calculs dupliquĂ©es sur la
requĂȘte principale fait rĂ©fĂ©rence Ă la requĂȘte WITH
plus d'une fois ; mais si chaque utilisation requiert seulement
quelques lignes de la sortie complĂšte de la requĂȘte
WITH
, la clause NOT MATERIALIZED
peut apporter un gain net en autorisant les requĂȘtes Ă ĂȘtre optimisĂ©es
globalement. NOT MATERIALIZED
est ignoré s'il est
attachĂ© Ă une requĂȘte WITH
récursive ou qui n'est pas
sans effet de bord (autrement dit, pas un simple SELECT
contenant aucune fonction volatile).
Par dĂ©faut, une requĂȘte WITH
sans effet de bord est
intĂ©grĂ©e dans la requĂȘte principale si elle est utilisĂ©e exactement une
fois dans la clause FROM
de la requĂȘte. Ceci permet une
optimisation de la jointure des deux requĂȘtes dans des situations oĂč cela
serait sĂ©mantiquement invisible. NĂ©anmoins, cette intĂ©gration peut ĂȘtre
empĂȘchĂ©e en marquant la requĂȘte WITH
avec le mot-clé
MATERIALIZED
. Ceci peut ĂȘtre utile si la requĂȘte
WITH
est utilisée comme barriÚre d'optimisation pour
empĂȘcher le planificateur de choisir un mauvais plan. Les versions de
PostgreSQL antérieures à la 12 ne faisaient
jamais ce type d'intĂ©gration, donc les requĂȘtes Ă©crites pour les versions
précédentes pourraient se fier sur WITH
comme barriĂšres
d'optimisation.
Voir Section 7.8 pour plus d'informations.
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 (via
WHERE
) 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.
TABLESAMPLE methode_echantillonnage
( argument
[, ...] ) [ REPEATABLE ( pourcentage_echantillon
) ]
Une clause TABLESAMPLE
aprĂšs un nom_table
indique que la methode_echantillonnage
indiquée doit
ĂȘtre utilisĂ© pour rĂ©cupĂ©rer un sous-ensemble des lignes de cette
table. Cet échantillonnage précÚde l'application de tout autre filtre
tel que la clause WHERE
. La distribution standard
de PostgreSQL inclut deux méthodes
d'échantillonnage, BERNOULLI
et
SYSTEM
mais d'autres méthodes d'échantillonnage
peuvent ĂȘtre installĂ©es via des extensions.
Les méthodes d'échantillonnage BERNOULLI
et
SYSTEM
acceptent chacune un seul argument
correspondant Ă la fraction Ă
échantillonner pour la table, exprimée sous la forme d'un pourcentage
entre 0 et 100. Cet argument peut ĂȘtre une expression renvoyant un
flottant (real
). (D'autres méthodes d'échantillonnage
pourraient accepter plus d'arguments ou des arguments différents.) Ces
deux méthodes retournent chacune un sous-ensemble choisi au hasard de
la table qui contiendra approximativement le pourcentage indiqué de
lignes pour cette table. La méthode BERNOULLI
parcourt la table complÚte et sélectionne ou ignore des lignes
individuelles indépendemment avec la probabilité sélectionnée. La
méthode SYSTEM
fait un échantillonnage au niveau
des blocs, chaque bloc ayant la chance indiquĂ©e d'ĂȘtre
sélectionnée ; toutes les lignes de chaque bloc sélectionné sont
renvoyées. La méthode SYSTEM
est bien plus rapide
que la méthode BERNOULLI
quand un petit pourcentage
est indiqué pour l'échantillonnage mais elle peut renvoyer un
échantillon moins aléatoire de la table, dû aux effets de l'ordre des
lignes.
La clause optionnelle REPEATABLE
indique un nombre
seed
ou une expression Ă
utiliser pour générer des nombres aléatoires pour la méthode
d'Ă©chantillonnage. La valeur peut ĂȘtre toute valeur flottante non
NULL. Deux requĂȘtes prĂ©cisant la mĂȘme valeur seed et les mĂȘmes valeurs
en argument
sĂ©lectionneront le mĂȘme Ă©chantillon de la table si celle-ci n'a pas
changé entre temps. Mais différentes valeurs seed produiront
généralement des échantillons différents. Si
REPEATABLE
n'est pas indiqué, alors un nouvel
Ă©chantillon est choisi au hasard pour chaque requĂȘte, basĂ© sur une
graine générée par le systÚme. Notez que
certaines méthodes d'échantillonage supplémentaires pourraient ne pas
accepter la clausse REPEATABLE
, et toujours
produire de nouveau échantillon à chaque utilisation.
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
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 de la
fonction était créée comme une table temporaire pour la durée de
cette seule commande SELECT
. Quand la clause
optionnelle WITH ORDINALITY
est ajoutée à l'appel
de la fonction, une nouvelle colonne est ajoutée aprÚs toutes les
colonnes en sortie de la fonction numérotant ainsi chaque ligne.
Un alias peut ĂȘtre fourni de la mĂȘme façon pour une table. Si un alias
de table est donnĂ©, une liste d'alias de colonnes peut aussi ĂȘtre Ă©crite
pour fournir des noms de substitution pour un ou plusieurs attributs du
type composite en retour de la fonction, ceci incluant la colonne ajoutée
par ORDINALITY
.
Plusieurs appels de fonction peuvent ĂȘtre combinĂ©s en un seul Ă©lĂ©ment
dans la clause FROM
en les entourant de ROWS
FROM( ... )
. La sortie d'un tel élément est la concaténation
de la premiĂšre ligne de chaque fonction, puis la deuxiĂšme ligne de
chaque fonction, etc. Si certaines fonctions produisent moins de lignes
que d'autres, des NULL sont ajoutées pour les données manquantes, ce
qui permet d'avoir comme nombre de lignes celui de la fonction qui en
renvoit le plus.
Si la fonction a été définie comme renvoyant le type de données
record
, un alias ou le mot clé AS
doivent
ĂȘtre prĂ©sents, suivi par une liste de dĂ©finition de colonnes de la
forme (
. La liste de définition des colonnes doit
correspondre au nombre réel et aux types réels des colonnes renvoyées
par la fonction.
nom_colonne
type_donnée
[, ...
])
Lors de l'utilisation de la syntaxe ROWS FROM( ... )
,
si une des fonctions nécessite une liste de définition des colonnes, il
est préférable de placer la liste de définition des colonnes aprÚs l'appel
de la fonction dans ROWS FROM( ... )
. Une liste ded
dĂ©finition des colonnes peut ĂȘtre placĂ© aprĂšs la construction
ROWS FROM( ... )
seulement s'il n'y a qu'une seule
fonction et pas de clause WITH ORDINALITY
.
Pour utiliser ORDINALITY
avec une liste de définition
de colonnes, vous devez utiliser la syntaxe ROWS
FROM( ... )
et placer la liste de définition de colonnes dans
ROWS FROM( ... )
.
type_jointure
Un des éléments
[ INNER ] JOIN
LEFT [ OUTER ] JOIN
RIGHT [ OUTER ] JOIN
FULL [ OUTER ] JOIN
Pour les types de jointures INNER
et
OUTER
, une condition de jointure doit ĂȘtre spĂ©cifiĂ©e,
Ă choisir parmi ON
ou
condition_jointure
USING (
ou
colonne_jointure
[, ...])NATURAL
. Voir ci-dessous pour les significations.
Une clause JOIN
combine deux éléments
FROM
, que nous allons appelons « tables »
par simplicitĂ© bien qu'ils puissent ĂȘtre n'importe quel Ă©lĂ©ment
utilisable dans une clause 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
.
Toutes les options JOIN
sont une facilité d'écriture
car elles ne font rien que vous ne pourriez faire avec les habituels
FROM
et WHERE
.
CROSS JOIN
et INNER JOIN
produisent un
simple produit cartésien. Le résultat est identique à celui obtenu
lorsque les deux tables 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 tables 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. 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
.
CROSS JOIN
CROSS JOIN
est équivalent à INNER JOIN ON
(TRUE)
, c'est-à -dire qu'aucune ligne n'est supprimée par la
qualification. Elles rĂ©alisent un produit cartĂ©sien, donc les mĂȘmes
résultats que vous obtiendriez en listant les deux tables au niveau haut
d'un FROM
, mais restreints Ă la condition de jointure
(s'il y en a une).
LATERAL
Le mot clé LATERAL
peut précéder un élément
sous-SELECT
de la clause FROM
. Ceci
permet au sous-SELECT
de faire référence aux colonnes
des éléments du FROM
qui apparaissent avant lui dans
la liste FROM
. (Sans LATERAL
, chaque
sous-SELECT
est évalué indépendamment et donc ne peut
pas faire référence à tout autre élément de la clause
FROM
.)
LATERAL
peut aussi précéder un élément fonction dans
la clause FROM
mais dans ce cas, ce n'est pas requis
car l'expression de la fonction peut faire référence aux éléments du
FROM
dans tous les cas.
Un élément LATERAL
peut apparaĂźtre au niveau haut
dans la liste FROM
ou à l'intérieur d'un arbre
JOIN
. Dans ce dernier cas, il peut aussi faire
référence à tout élément qui se trouvent à la gauche d'un
JOIN
qui est Ă sa droite.
Quand un élément du FROM
des références
LATERAL
, l'évaluation se fait ainsi : pour chaque
ligne d'un élément FROM
fournissant une colonne
référencée ou un ensemble de lignes provenant de plusieurs éléments
FROM
fournissant les colonnes, l'élément
LATERAL
est évaluée en utilisant la valeur des
colonnes de cette (ou ces) ligne(s). Les lignes résultantes sont
jointes comme d'habitude avec les lignes pour lesquelles elles ont
été calculées. Ceci est répété pour chaque ligne ou chaque ensemble de
lignes provenant de la table contenant les colonnes référencées.
Le(s) table(s) contenant les colonnes rĂ©fĂ©rencĂ©es doivent ĂȘtre jointes
avec INNER
ou LEFT
à l'élément
LATERAL
. Sinon il n'y aurait pas un ensemble bien
défini de lignes à partir duquel on pourrait construire chaque ensemble
de lignes pour l'élément LATERAL
. Du coup, bien qu'une
construction comme
est valide
syntaxiquement, il n'est pas permis Ă X
RIGHT JOIN
LATERAL Y
Y
de
référencer X
.
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.
GROUP BY
La clause GROUP BY
optionnelle a la forme générale
GROUP BY element_regroupement
[, ...]
GROUP BY
condensera en une seule ligne toutes les
lignes sĂ©lectionnĂ©es partageant les mĂȘmes valeurs pour les expressions
regroupées. Une expression
utilisée à l'intérieur d'un element_regroupement
peut ĂȘtre un nom de
colonne en entrée, ou le nom ou le numéro d'une colonne en sortie (élément
de la liste SELECT
), ou une expression arbitraire
formée à partir des valeurs ou colonnes en entrée. En cas d'ambiguité, un
nom GROUP BY
sera interprété comme un nom de colonne en
entrée plutÎt qu'en tant que nom de colonne en sortie.
Si une clause parmi GROUPING SETS
,
ROLLUP
ou CUBE
est présente comme
élément de regroupement, alors la clause GROUP BY
dans
sa globalité définit un certain nombre d'ensembles de
regroupement
indépendants. L'effet de ceci est l'équivalent
de la construction d'un UNION ALL
des sous-requĂȘtes
pour chaque ensemble de regroupement individuel avec leur propre clause
GROUP BY
. Pour plus de détails sur la gestion des
ensembles de regroupement, voir Section 7.2.4.
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. (S'il
y a des fonctions d'agrégat mais pas de clause GROUP BY
,
la requĂȘte est traitĂ©e comme ayant un seul groupe contenant toutes les lignes
sélectionnées.)
L'ensemble de lignes envoyĂ©es Ă la fonction d'agrĂ©gat peut ĂȘtre en plus filtrĂ©
en ajoutant une clause FILTER
lors de l'appel Ă la fonction
d'agrégat ; voir Section 4.2.7 pour plus
d'informations. Quand une clause FILTER
est présente,
seules les lignes correspondant au filtre sont incluses en entrée de cette
fonction d'agrégat.
Quand GROUP BY
est présent ou que des fonctions d'agrégat
sont présentes, 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.
Rappelez-vous que toutes les fonctions d'agrégat sont évaluées avant
l'évaluation des expressions « scalaires » dans la clause
HAVING
ou la liste SELECT
. Ceci
signifie que, par exemple, une expression CASE
ne
peut pas ĂȘtre utilisĂ©e pour ignorer l'Ă©valuation de la fonction
d'agrégat ; voir Section 4.2.14.
Actuellement, FOR NO KEY UPDATE
, FOR
UPDATE
, FOR SHARE
et FOR KEY
SHARE
ne peuvent pas ĂȘtre spĂ©cifiĂ©es avec GROUP
BY
.
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 ou que les colonnes non groupées sont fonctionnement dépendantes
des colonnes groupées.
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.
Actuellement, FOR NO KEY UPDATE
, FOR
UPDATE
, FOR SHARE
et FOR KEY
SHARE
ne peuvent pas ĂȘtre spĂ©cifiĂ©es avec GROUP
BY
.
WINDOW
La clause optionnelle WINDOW
a la forme générale
WINDOWnom_window
AS (définition_window
) [, ...]
oĂč nom_window
est un nom qui
peut ĂȘtre rĂ©fĂ©rencĂ© par des clauses OVER
ou par des
définitions Window, et
définition_window
est
[nom_window_existante
] [ PARTITION BYexpression
[, ...] ] [ ORDER BYexpression
[ ASC | DESC | USINGoperateur
] [ 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 | GROUPS }début_portée
[exclusion_portée
] { RANGE | ROWS | GROUPS } BETWEENdébut_portée
ANDfin_portée
[exclusion_portée
]
oĂč dĂ©but_frame
et fin_frame
peuvent valoir
UNBOUNDED PRECEDINGdécalage
PRECEDING CURRENT ROWdécalage
FOLLOWING UNBOUNDED FOLLOWING
et exclusion_portée
peut valoir
EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS
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 les options
frame_start
et frame_end
que le choix
début_frame
-- par exemple
RANGE BETWEEN CURRENT ROW AND
n'est pas permis.
décalage
PRECEDING
L'option de portée par défaut est RANGE UNBOUNDED
PRECEDING
, qui est identique Ă RANGE BETWEEN UNBOUNDED
PRECEDING AND CURRENT ROW
; cela configure la portĂ©e Ă
toutes les lignes du début de la partition jusqu'au dernier
peer de la ligne courant (une ligne que la clause
ORDER BY
de fenĂȘtrage considĂšre Ă©quivalente Ă la ligne
courante ; toutes les lignes sont dans ce cas s'il n'y a pas
d'ORDER BY
). En général, UNBOUNDED
PRECEDING
signifie que la portée comment avec la premiÚre ligne
de la partition et, de façon similaire, UNBOUNDED
FOLLOWING
signifie que la portée se termine avec la derniÚre
ligne de la partition, quelque soit le mot (RANGE
,
ROWS
or GROUPS
). Dans le mode
ROWS
, CURRENT ROW
signifie que la
portée commence ou se termine avec la ligne actuelle ; mais dans les
modes RANGE
et GROUPS
, il signifie
que la portée commence ou se termine avec le premier ou le dernier
équivalent de la ligne courante d'aprÚs le tri ORDER
BY
. Les options offset
PRECEDING
et offset
FOLLOWING
varient en signification suivant le mode de
portée. Dans le mode ROWS
,
offset
est un entier indiquant que la portée
commence ou se termine par ce nombre de lignes avant ou aprĂšs la ligne
actuelle. Dans le mode GROUPS
,
offset
est un entier indiquant que la portée
commence ou se termine par ce nombre de groupes d'équivalents avant ou
aprĂšs le groupe d'Ă©quivalents de la ligne courante, oĂč un
groupe d'équivalents est un groupe de lignes
équivalentes suivant la clause ORDER BY
de fenĂȘtrage.
Dans le mode RANGE
, l'utilisation de l'option
offset
requiert qu'il y ait exactement une
colonne ORDER BY
dans la dĂ©finition de la fenĂȘtre.
Ensuite, la portée contient ces lignes dont la valeur de la colonne de tri
n'est pas inférieur de offset
(pour
PRECEDING
) ou supérieur (pour
FOLLOWING
) Ă la valeur de la colonne de tri de la ligne
courante. Dans ces cas, le type de données de l'expression
offset
dépend du typ de données de la colonne
de tri. Pour les colonnes numĂ©riques, il s'agit typiquement du mĂȘme type
que la colonne de tri. Pour les colonnes date/heure, il s'agit typiquement
d'un interval
. Dans tous les cas, la valeur de
offset
doit ĂȘtre non NULL et non nĂ©gative. De
plus, alors que offset
n'a pas besoin d'ĂȘtre
une simple constante, elle ne peut pas contenir des variables, des
fonctions d'agrĂ©gat et des fonctions de fenĂȘtrage.
L'option exclusion_portée
autorise les lignes
autour de la ligne courante d'ĂȘtre exclues de la portĂ©e, mĂȘme si elles
devraient ĂȘtre includes d'aprĂšs les options de dĂ©but et de fin de portĂ©e.
EXCLUDE CURRENT ROW
exclut la ligne courante de la
portée. EXCLUDE GROUP
exclut la ligne courante et ses
équivalents de tri à partir de la portée. EXCLUDE TIES
exclut tout équivalent de la ligne courante à partir de la portée, mais
pas la ligne courante elle-mĂȘme. EXCLUDE NO OTHERS
indique seulement explicitement le comportement par défaut qui est de ne
pas exclure la ligne courante et ses équivalents.
Notez que le mode ROWS
peut produire des résultats
inattendus si la clause ORDER BY
ne trie pas les lignes
de façon unique. Les modes RANGE
et
GROUPS
sont conçus pour s'assurer que les lignes
équivalents d'aprÚs le tri ORDER BY
sont traitées de la
mĂȘme façon : toutes les lignes d'un groupe d'Ă©quivalent sera inclus
dans la portée ou en sera exclus.
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.
Actuellement, FOR NO KEY UPDATE
, FOR
UPDATE
, FOR SHARE
et FOR KEY
SHARE
ne peuvent pas ĂȘtre spĂ©cifiĂ©es avec GROUP
BY
.
Les fonctions window sont décrites en détail dans Section 3.5, Section 4.2.8 et Section 7.2.5.
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). 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,
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
nom_table
.*AS
;
les noms des colonnes de sorties seront les mĂȘme que ceux de la table.
Suivant le standard SQL, les expressions dans la liste en sortie doivent
ĂȘtre calculĂ©es avant d'appliquer les clauses DISTINCT
,
ORDER BY
et LIMIT
. Ceci est
évidemment nécessaire lors de l'utilisation de DISTINCT
car, dans le cas contraire, il est difficile de distinguer les valeurs.
Néanmoins, dans de nombreux cas, il est plus intéressant que les
expressions en sortie soient calculées aprÚs les clauses ORDER
BY
et LIMIT
, tout particuliĂšrement si la liste
en sortie contient des fonctions volatiles ou coûteuses. Avec ce
comportement, l'ordre d'évaluation des fonctions est plus intuitive et il
n'y aurait pas d'évaluations correspondant aux lignes n'apparaissant pas
en sortie. PostgreSQL évaluera réellement les
expressions en sortie aprĂšs le tri et la limite, si tant est que ces
expressions ne sont pas référencées dans les clauses
DISTINCT
, ORDER BY
et GROUP BY
. (En contre-exemple, SELECT
f(x) FROM tab ORDER BY 1
doit forcément évaluer
f(x)
avant de réaliser le tri.) Les expressions en
sortie contenant des fonctions renvoyant plusieurs lignes sont réellement
évaluées aprÚs le tri et avant l'application de la limite, pour que
LIMIT
permette d'éviter l'exécution inutile de la
fonction.
Les versions de PostgreSQL antérieures à la 9.6 ne fournissaient pas de garantie sur la durée de l'évaluation des expressions en sortie par rapport aux tris et aux limites. Cela dépendait de la forme du plan d'exécution sélectionné.
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 (
conserve seulement la premiÚre ligne de chaque ensemble de lignes pour lesquelles le résultat
de l'expression est identique. Les expressions expression
[, ...] )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
.
Actuellement, FOR NO KEY UPDATE
, FOR
UPDATE
, FOR SHARE
et FOR KEY
SHARE
ne peuvent pas ĂȘtre spĂ©cifiĂ©es avec
DISTINCT
.
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 NO KEY UPDATE
, FOR UPDATE
,
FOR SHARE
et FOR KEY SHARE
ne peuvent
pas ĂȘtre spĂ©cifiĂ©s pour un rĂ©sultat d'UNION
ou pour toute entrée
d'un UNION
.
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 NO KEY UPDATE
, FOR UPDATE
,
FOR SHARE
ou FOR KEY 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 NO KEY UPDATE
, FOR UPDATE
,
FOR SHARE
et FOR KEY SHARE
ne peuvent
pas ĂȘtre spĂ©cifiĂ©s pour un rĂ©sultat d'INTERSECT
ou pour une
entrée d'INTERSECT
.
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 NO KEY UPDATE
,
FOR UPDATE
, FOR SHARE
ou
FOR KEY 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 NO KEY UPDATE
, FOR UPDATE
,
FOR SHARE
et FOR KEY SHARE
ne peuvent
pas ĂȘtre spĂ©cifiĂ©s dans un rĂ©sultat EXCEPT
ou pour une entrée
d'un EXCEPT
.
ORDER BY
La clause optionnelle ORDER BY
a la forme
générale :
ORDER BYexpression
[ ASC | DESC | USINGopé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
et Section 23.2.
LIMIT
La clause LIMIT
est constituée de deux sous-clauses
indépendantes :
LIMIT {nombre
| ALL } OFFSETdé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.
OFFSETdébut
{ ROW | ROWS } FETCH { FIRST | NEXT } [compte
] { ROW | ROWS } ONLY
Avec cette syntaxe, le standard SQL exige que la valeur de start
ou count
soit une constante litérale, un
paramĂštre ou un nom de variable. PostgreSQL
propose en extension l'utilisation d'autres expressions. Ces derniĂšres
devront gĂ©nĂ©ralement ĂȘtre entre parenthĂšses pour Ă©viter toute ambiguĂŻtĂ©.
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.
FOR UPDATE
, FOR NO KEY UPDATE
,
FOR SHARE
et FOR KEY SHARE
sont des
clauses de verrouillage. Elles affectent la façon
dont SELECT
verrouille les lignes au moment de leur
obtention sur la table.
La clause de verrouillage a la forme suivante :
FORforce_verrou
[ OFnom_table
[, ...] ] [ NOWAIT | SKIP LOCKED ]
oĂč force_verrou
fait partie de :
UPDATE NO KEY UPDATE SHARE KEY SHARE
Pour plus d'informations sur chaque mode de verrouillage au niveau ligne, voir Section 13.3.2.
Pour éviter que l'opération attende la validation d'autres transactions,
utilisez soit l'option NOWAIT
soit l'option
SKIP LOCKED
. Avec NOWAIT
,
l'instruction renvoie une erreur, plutĂŽt que de rester en attente, si une
ligne sĂ©lectionnĂ©e ne peut pas ĂȘtre immĂ©diatement verrouillĂ©e. Avec
SKIP LOCKED
, toute ligne sélectionnée qui ne peut pas
ĂȘtre immĂ©diatement verrouillĂ©e est ignorĂ©e. Ignorer les lignes
verrouillées fournit une vue incohérente des données, donc ce n'est pas
acceptable dans un cadre gĂ©nĂ©ral, mais ça peut ĂȘtre utilisĂ© pour Ă©viter
les contentions de verrou lorsque plusieurs consommateurs cherchent Ă
accéder à une table de style queue. Notez que NOWAIT
et
SKIP LOCKED
s'appliquent seulement au(x) verrou(x)
niveau ligne -- le verrou niveau table ROW SHARE
est toujours pris de façon ordinaire (voir Chapitre 13).
L'option NOWAIT
de LOCK peut
toujours ĂȘtre utilisĂ©e pour acquĂ©rir le verrou niveau table sans attendre.
Si des tables particuliÚres sont nommées dans une clause de verrouillage,
alors seules les lignes provenant de ces tables sont verrouillées ;
toute autre table utilisée dans le SELECT
est simplement
lue. Une clause de verrouillage sans liste de tables affecte toutes les
tables utilisées dans l'instruction. Si une clause de verrouillage 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, ces clauses 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 une clause de verrouillage à l'intérieur
de la requĂȘte WITH
.
Plusieurs clauses de verrouillage 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 plus
d'une clause de verrouillage, alors elle est traitée comme la clause la plus
forte. 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. Sinon, il
est traité comme SKIP LOCKED
si c'est indiqué dans une
des clauses qui l'affectent.
Les clauses de verrouillage 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 une clause de verrouillage
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 une clause de verrouillage
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 une clause de verrouillage apparait 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.
Les anciennes versions échouaient à préserver un verrou qui est mis à jour par un point de sauvegarde ultérieur. Par exemple, ce code :
BEGIN; SELECT * FROM ma_table WHERE cle = 1 FOR UPDATE; SAVEPOINT s; UPDATE ma_table SET ... WHERE cle = 1; ROLLBACK TO s;
va échouer à conserver le verrou FOR UPDATE
aprĂšs la
commande ROLLBACK TO
. Ceci a été corrigé en 9.3.
Il est possible qu'une commande SELECT
exécutée
au niveau d'isolation READ COMMITTED
et utilisant
ORDER BY
et une clause de verrouillage
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.
TABLE
La commande
TABLE nom
est Ă©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. Seuls les clauses de verrou de
WITH
, UNION
,
INTERSECT
, EXCEPT
, ORDER
BY
, LIMIT
, OFFSET
,
FETCH
et FOR
peuvent ĂȘtre utilisĂ©es
avec TABLE
; la clause WHERE
et
toute forme d'agrĂ©gation ne peuvent pas ĂȘtre utilisĂ©es.
Joindre la table films
avec la table
distributeurs
:
SELECT f.titre, f.did, d.nom, f.date_prod, f.genre FROM distributeurs d JOIN films f USING (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
Voici un exemple d'une fonction avec la colonne ordinality :
SELECT * FROM unnest(ARRAY['a','b','c','d','e','f']) WITH ORDINALITY; unnest | ordinality --------+---------- a | 1 b | 2 c | 3 d | 4 e | 5 f | 6 (6 rows)
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 pour
plus d'exemples).
Cet exemple utilise LATERAL
pour appliquer une fonction
renvoyant des lignes, recupere_nom_produits()
, pour
chaque ligne de la table manufacturiers
:
SELECT m.nom AS mnom, pnom FROM manufacturiers m, LATERAL recupere_nom_produits(m.id) pnom;
Les manufacturiers qui n'ont pas encore de produits n'apparaĂźtront pas dans le rĂ©sultat car la jointure est interne. Si vous voulons inclure les noms de ces manufacturiers, la requĂȘte doit ĂȘtre Ă©crite ainsi :
SELECT m.name AS mnom, pnom FROM manufacturiers m LEFT JOIN LATERAL recupere_nom_produits(m.id) pnom ON true;
L'instruction SELECT
est évidemment compatible avec le
standard SQL. Mais il y a des extensions et quelques fonctionnalités
manquantes.
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é.
SELECT
vides
La liste des expressions en sortie aprĂšs SELECT
peut
ĂȘtre vide, produisant ainsi une table de rĂ©sultats Ă zĂ©ro colonne. Ceci
n'est pas une syntaxe valide suivant le standard SQL.
PostgreSQL l'autorise pour ĂȘtre cohĂ©rent avec le
fait qu'il accepte des tables à zéro colonne. Néanmoins, une liste vide
n'est pas autorisé quand un DISTINCT
est utilisé.
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
.)
TABLESAMPLE
La clause TABLESAMPLE
est actuellement seulement
acceptée pour les tables standards et les vues matérialisées. D'aprÚs le
standard SQL, il devrait ĂȘtre possible de l'appliquer Ă tout Ă©lĂ©ment
faisant partie de la clause FROM
.
FROM
PostgreSQL autorise un appel de fonction dans
la liste FROM
. Pour le standard SQL, il serait
nécessaire de placer cet appel de fonction dans un
sous-SELECT
; autrement dit, la syntaxe
FROM
est Ă peu prĂšs Ă©quivalente Ă
fonc
(...) alias
FROM LATERAL (SELECT
.
Notez que fonc
(...)) alias
LATERAL
est considéré comme étant
implicite ; ceci est dû au fait que le standard réclame la sémantique de
LATERAL
pour un élément UNNEST()
dans
la clause FROM
.
PostgreSQL traite UNNEST()
de
la mĂȘme façon que les autres fonctions renvoyant des lignes.
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.
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.
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 NO KEY UPDATE
, FOR UPDATE
, FOR SHARE
, FOR KEY 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.
Les variantes FOR NO KEY UPDATE
, FOR
SHARE
et FOR KEY SHARE
, ainsi que
NOWAIT
et SKIP LOCKED
,
n'apparaissent pas dans le standard.
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.
La clause DISTINCT ON
est une extension du standard
SQL.
ROWS FROM( ... )
est une extension du standard
SQL.
Les options MATERIALIZED
et NOT
MATERIALIZED
de la clause WITH
sont des
extensions au standard SQL.