IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Synopsis

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ AS nom_d_affichage ] [, ...]
    [ FROM éléments_from [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]
    [ ORDER BY expression [ ASC | DESC | USING opérateur ] [, ...] ]
    [ LIMIT { nombre | ALL } ]
    [ OFFSET début ]
    [ 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_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 [, ...] ) ]

Description

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

  1. 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 Clause FROM ci-dessous.)

  2. Si la clause WHERE est spécifiée, toutes les lignes qui ne satisfont pas les conditions sont éliminées de l'affichage. (Voir Clause WHERE ci-dessous.)

  3. 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 Clause GROUP BY et Clause HAVING ci-dessous.)

  4. Les lignes retournées sont traitées en utilisant les expressions de sortie de SELECT pour chaque ligne sélectionnée. (Voir Liste SELECT ci-dessous.)

  5. 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é. (Voir Clause UNION , Clause INTERSECT et Clause EXCEPT ci-dessous.)

  6. 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 Clause ORDER BY ci-dessous.)

  7. DISTINCT élimine les lignes dupliquées du résultat. DISTINCT ON élimine les lignes qui correspondent à toutes les expressions données. ALL (la valeur par défaut) renvoie toutes les lignes candidates, y compris les lignes dupliquées. (Voir Clause DISTINCT ci-dessous.)

  8. Si les clauses LIMIT ou OFFSET sont spécifiées, l'instruction SELECT ne renvoie qu'un sous-ensemble de lignes de résultats. (Voir Clause LIMIT ci-dessous.)

  9. 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 Clause FOR UPDATE/FOR SHARE ci-dessous.)

Le droit SELECT sur une table est nécessaire pour lire ses valeurs. L'utilisation de FOR UPDATE ou de FOR SHARE requiert en plus le droit UPDATE.

Paramètres

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 existante ou d'une vue. Si ONLY est spécifié, seule cette table est parcourue. Dans le cas contraire, la table et toutes ses descendantes (s'il y en a) sont parcourues. * peut être ajouté au nom de la table pour indiquer que les tables descendantes doivent être parcourues mais, dans la version actuelle, c'est le comportement par défaut. Dans les versions précédant la 7.1, ONLY était le comportement par défaut. Ce dernier peut être modifié à l'aide de l'option de configuration sql_inheritance.

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 foo AS, le reste du SELECT doit faire référence à cet élément de FROM par f et non pas par foo. 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 peut aussi être utilisée ici.

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.

Clause ORDER BY

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

ORDER BY expression [ ASC | DESC | USING opérateur ] [, ...]

expression est le nom ou le numéro ordinal d'une colonne en sortie (élément de la liste SELECT ) ou une expression quelconque formée à partir des valeurs des colonnes en entrée.

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.

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. 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.

La valeur NULL est considérée supérieure à toute autre valeur. En d'autres termes, avec un ordre de tri ascendant, les valeurs NULL sont triées à la fin et avec un ordre de tri descendant, elles sont triées au début.

Les données de chaînes de caractères sont triées suivant l'ordre spécifique à la locale, ordre établi au moment de la création du groupe de bases de données.

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). Pour plus d'informations, voir Chapitre 12, Contrôle d'accès simultané.

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 12, Contrôle d'accès simultané). L'option NOWAIT de LOCK peut toujours être utilisée pour acquérir le verrou niveau table sans attendre.

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 .

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 la commande. 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.

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'aggrégats.

[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 transation 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 qui utilise simultanément les clauses LIMIT et FOR UPDATE/SHARE retourne moins de lignes que le nombre spécifié par LIMIT. En effet, LIMIT est appliqué le premier. La commande sélectionne le nombre de lignes spécifiées, mais peut être bloquée en essayant d'obtenir un verrou sur l'une ou l'autre de ces lignes. Lorsque le SELECT est débloqué, la ligne peut avoir été supprimée ou modifiée de telle sorte qu'elle ne remplisse plus les conditions imposées par la clause WHERE. Dans ce cas, elle n'est pas retournée.

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

Compatibilité

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