Chapitre 4. Syntaxe SQL

Table des matières
4.1. Structure lexicale
4.1.1. Identifieurs et mots clés
4.1.2. Constantes
4.1.3. Opérateurs
4.1.4. Caractères spéciaux
4.1.5. Commentaires
4.1.6. Précédence lexicale
4.2. Expressions de valeurs
4.2.1. Références de colonnes
4.2.2. Paramètres de position
4.2.3. Indices
4.2.4. Sélection de champs
4.2.5. Appels d'opérateurs
4.2.6. Appels de fonctions
4.2.7. Expressions d'agrégat
4.2.8. Conversions de type
4.2.9. Sous-requêtes scalaires
4.2.10. Constructeurs de tableaux
4.2.11. Règles d'évaluation des expressions

Ce chapitre décrit la syntaxe de SQL. Il donne les fondements pour comprendre les chapitres suivants qui iront plus en détail sur la façon dont les commandes SQL sont appliquées pour définir et modifier des données.

Nous avertissons aussi nos utilisateurs, déjà familiers avec le SQL, qu'ils doivent lire ce chapitre très attentivement car il existe plusieurs règles et concepts implémentés différemment suivant les bases de données SQL ou spécifiques à PostgreSQL.

4.1. Structure lexicale

Une entrée SQL consiste en une séquence de commandes. Une commande est composée d'une séquence de jetons, terminés par un point-virgule (<< ; >>). La fin du flux en entrée se termine aussi par une commande. Les jetons valides dépendent de la syntaxe particulière de la commande.

Un jeton peut être un mot clé, un identifiant, un identifiant entre guillemets, un littéral (ou une constante) ou un symbole de caractère spécial. Les jetons sont normalement séparés par des espaces blancs (espace, tabulation, nouvelle ligne) mais n'ont pas besoin de l'être s'il n'y a pas d'ambiguïté (ce qui est seulement le cas si un caractère spécial est adjacent à des jetons d'autres types).

De plus, des commentaires peuvent se trouver dans l'entrée SQL. Ce ne sont pas des jetons, ils sont réellement équivalents à un espace blanc.

Par exemple, ce qui suit est (syntaxiquement) valide pour une entrée SQL :

SELECT * FROM MA_TABLE;
UPDATE MA_TABLE SET A = 5;
INSERT INTO MA_TABLE VALUES (3, 'salut ici');

C'est une séquence de trois commandes, une par ligne (bien que cela ne soit pas requis ; plusieurs commandes pourraient se trouver sur une même ligne et les commandes peuvent être placées sur plusieurs lignes).

La syntaxe SQL n'est pas très consistante en ce qui concerne les jetons identifiants des commandes et lesquels sont des opérandes ou des paramètres. Les premiers jetons sont généralement le nom de la commande. Dans l'exemple ci-dessus, nous parlons d'une commande << SELECT >>, d'une commande << UPDATE >> et d'une commande << INSERT >>. Mais en fait, la commande UPDATE requiert toujours un jeton SET apparaissant dans une certaine position, et cette variante particulière de INSERT requiert aussi un VALUES pour être complète. Les règles de syntaxe précises pour chaque commande sont décrites dans la Partie VI.

4.1.1. Identifieurs et mots clés

Les jetons tels que SELECT, UPDATE ou VALUES dans l'exemple ci-dessus sont des exemples de mots clés, c'est-à-dire des mots qui ont une signification dans le langage SQL. Les jetons MA_TABLE et A sont des exemples d'identifiants. Ils identifient des noms de tables, colonnes ou d'autres objets de la base de données suivant la commande qui a été utilisée. Du coup, ils sont quelques fois simplement nommés des << noms >>. Les mots clés et les identifiants ont la même structure lexicale, signifiant que quelqu'un ne peut pas savoir si un jeton est un identifiant ou un mot clé sans connaître le langage. Une liste complète des mots clé est disponible dans l'Annexe C.

Les identifiants et les mots clés SQL doivent commencer avec une lettre (a-z, mais aussi des lettres de marques diacritiques différentes et des lettres non latines) ou un tiret bas (_). Les caractères suivants dans un identifiant ou dans un mot clé peuvent être des lettres, des tirets-bas, des chiffres (0-9) ou des signes dollar ($). Notez que les signes dollar ne sont pas autorisés en tant qu'identifiant suivant le standard SQL, donc leur utilisation pourrait rendre les applications moins portables. Le standard SQL ne définira pas un mot clé contenant des chiffres ou commençant ou finissant par un tiret bas, donc les identifiants de cette forme sont sûr de passer les conflits possibles avec les futures extensions du standard.

Le système utilise pas plus de NAMEDATALEN-1 caractères d'un identifiant ; les noms longs peuvent être écrits dans des commandes mais ils seront tronqués. Par défaut, NAMEDATALEN vaut 64. Du coup, la taille maximum de l'identifiant est de 63. Si cette limite est problématique, elle peut être élevée en modifiant NAMEDATALEN dans src/include/postgres_ext.h.

L'identifiant et les noms de mots clés sont insensibles à la casse. Du coup,

UPDATE MA_TABLE SET A = 5;

peut aussi s'écrire de cette façon

uPDaTE ma_TabLE SeT a = 5;

Une convention souvent utilisée est d'écrire les mots clés en majuscule et les noms en minuscule, c'est-à-dire

UPDATE ma_table SET a = 5;

Voici un deuxième type d'identifiant : l'identifiant délimité ou l'identifiant entre guillemets. Il est formé en englobant une séquence arbitraire de caractères entre des guillemets doubles ("). Un identifiant délimité est toujours un identifiant, jamais un mot clé. Donc, "select" pourrait être utilisé pour faire référence à une colonne ou à une table nommée << select >>, alors qu'un select sans guillemets sera pris pour un mot clé et du coup, pourrait provoquer une erreur d'analyse lorsqu'il est utilisé alors qu'un nom de table ou de colonne est attendu. L'exemple peut être écrit avec des identifiants entre guillemets comme ceci :

UPDATE "ma_table" SET "a" = 5;

Les identifiants entre guillemets peuvent contenir tout caractère autre qu'un guillemet double. (Pour inclure un guillemet double, écrivez deux guillemets doubles.) Ceci permet la construction de noms de tables et de colonnes qui ne seraient pas possibles autrement, comme des noms contenant des espaces ou des arobases. La limitation de la longueur s'applique toujours.

Mettre un identifiant entre guillemets le rend sensible à la casse alors que les noms sans guillemets sont toujours convertis en minuscules. Par exemple, les identifiants FOO, foo et "foo" sont considérés identiques par PostgreSQL mais "Foo" et "FOO" sont différents des trois autres et entre eux. (La mise en minuscule des noms sans guillemets avec PostgreSQL n'est pas compatible avec le standard SQL qui indique que les noms sans guillemets devraient être mis en majuscule. Du coup, foo devrait être équivalent à "FOO" et non pas à "foo" en respect avec le standard. Si vous voulez écrire des applications portables, nous vous conseillons de toujours mettre entre guillemets un nom particulier ou de ne jamais le mettre.)

4.1.2. Constantes

Il existe trois types implicites de constantes dans PostgreSQL : les chaînes, les chaînes de bits et les nombres. Les constantes peuvent aussi être spécifiées avec des types explicites, ce qui peut activer des représentations plus précises et gérées plus efficacement par le système. Les constantes implicites sont décrites ci-dessous ; les constantes explicites sont discutées après.

4.1.2.1. Constantes de chaînes

Une constante de type chaîne en SQL est une séquence arbitraire de caractères entourée par des guillemets simples ('), c'est-à-dire 'Ceci est une chaîne'. SQL permet aux guillemets simples d'être intégrés dans des chaînes en saisissant deux guillemets simples, par exemple 'Le cheval d''Anne'. Avec PostgreSQL, les guillemets simples pourraient être échappés avec un antislash (\), par exemple 'Le cheval d\'Anne'.

Des échappements style C sont aussi disponibles : \b est un retour arrière, \f est un retour chariot, \n est une nouvelle ligne, \r est un retour chariot, \t est une tabulation et \xxx, où xxx est un nombre en octal, est un octet avec la code correspondant. (Il est de votre responsabilité que les séquences d'octets créées soient composées de caractères valides dans le codage de l'ensemble des caractères.) Tout autre caractère suivant un antislash est pris littéralement. Du coup, pour inclure un antislash dans une constante de type chaîne, saisissez deux antislashs.

Le caractère de code zéro ne peut pas être dans une constante de type chaîne.

Deux constantes de type chaîne séparées par un espace blanc avec au moins une nouvelle ligne sont concaténées et traitées réellement comme si la chaîne avait été écrite dans une constante. Par exemple :

SELECT 'foo'
'bar';

est équivalent à

SELECT 'foobar';

mais

SELECT 'foo'      'bar';

n'a pas une syntaxe valide. (Ce comportement légèrement bizarre est spécifié par le standard SQL ; PostgreSQL suit le standard.)

4.1.2.2. Constantes de chaînes de bits

Les constantes de chaînes de bits ressemblent aux constantes de chaînes avec un B (majuscule ou minuscule) juste avant le guillemet du début (sans espace blanc), c'est-à-dire B'1001'. Les seuls caractères autorisés dans les constantes de type chaîne de bits sont 0 et 1.

Autrement, les constantes de chaînes de bits peuvent être spécifiées en notation hexadécimale en utilisant un X avant (minuscule ou majuscule), c'est-à-dire X'1FF'. Cette notation est équivalente à une constante de chaîne de bits avec quatre chiffres binaires pour chaque chiffre hexadécimal.

Les deux formes de constantes de chaînes de bits peuvent être continuées sur plusieurs lignes de la même façon que les constantes de chaînes habituelles.

4.1.2.3. Constantes numériques

Les constantes numériques sont acceptées dans ces formes générales :

chiffres
chiffres.
[chiffres]
[e[+-]chiffres]
[chiffres].
chiffres[e[+-]chiffres]
chiffres
e[+-]chiffres

chiffres est un ou plusieurs chiffres décimaux (de 0 à 9). Au moins un chiffre doit être avant ou après le point décimal, s'il est utilisé. Au moins un chiffre doit suivre l'indicateur d'exponentiel (e), s'il est présent. Il pourrait ne pas y avoir d'espaces ou d'autres caractères imbriqués dans la constante. Notez que tout signe plus ou moins en avant n'est pas forcément considéré comme faisant part de la constante ; il est un opérateur appliqué à la constante.

Il existe des exemples de constantes numériques valides :

42
3.5
4.
.001
5e2
1.925e-3

Une constante numérique contenant soit un point décimal soit un exposant est tout d'abord présumée du type integer si sa valeur est contenue dans le type integer (32 bits) ; sinon, il est présumé de type bigint si sa valeur entre dans un type bigint (64 bits) ; sinon, il est pris pour un type numeric. Les constantes contenant des poins décimaux et/ou des exposants sont toujours présumées de type numeric.

Le type de données affecté initialement à une constante numérique est seulement un point de départ pour les algorithmes de résolution de types. Dans la plupart des cas, la constante sera automatiquement convertie dans le type le plus approprié suivant le contexte. Si nécessaire, vous pouvez forcer l'interprétation d'une valeur numérique sur un type de données spécifiques en la convertissant. Par exemple, vous pouvez forcer une valeur numérique à être traitée comme un type real (float4) en écrivant

REAL '1.23'  -- style chaîne
1.23::REAL   -- style PostgreSQL (historique)

4.1.2.4. Constantes d'autres types

Une constante de type arbitrary peut être saisie en utilisant une des notations suivantes :

type 'chaîne'
'chaîne'::type
CAST ( 'chaîne' AS type )

Le texte de la chaîne est passé dans la routine de conversion pour le type appelé type. Le résultat est une constante du type indiqué. La conversion explicite de type pourrait être omise s'il n'y a pas d'ambiguïté sur le type de la constante (par exemple, lorsqu'elle est passée en argument à une fonction non surchargée), auquel cas elle est convertie automatiquement.

Il est aussi possible de spécifier une convertion de type en utilisant une syntaxe style fonction :

nomtype ( 'chaîne' )

mais tous les noms de type ne peuvent pas être utilisés ainsi ; voir la Section 4.2.8 pour plus de détails.

Les syntaxes ::, CAST() et d'appels de fonctions peuvent aussi être utilisées pour spécifier les conversions de type à l'exécution d'expressions arbitraires, comme discuté dans la Section 4.2.8. Mais, la forme type 'chaîne' peut seulement être utilisée pour spécifier le type d'une constante littérale. Une autre restriction sur type 'chaîne' est qu'il ne fonctionne pas pour les types de tableau ; utilisez :: ou CAST() pour spécifier le type d'une constante de type tableau.

4.1.3. Opérateurs

Un nom d'opérateur est une séquence d'au plus NAMEDATALEN-1 (63 par défaut) caractères provenant de la liste suivante :

+ - * / < > = ~ ! @ # % ^ & | ` ?

Néanmoins, il existe quelques restrictions sur les noms d'opérateurs :

  • -- et /* ne peuvent pas apparaître quelque part dans un nom d'opérateur car ils seront pris comme le début d'un commentaire.

  • Un nom d'opérateur à plusieurs caractères ne peut pas finir avec + ou -, sauf si le nom contient aussi un de ces trois caractères :

    ~ ! @ # % ^ & | ` ?

    Par exemple, @- est un nom d'opérateur autorisé, mais *- ne l'est pas. Cette restriction permet à PostgreSQL d'analyser des requêtes compatibles avec SQL sans requérir des espaces entre les jetons.

Lors d'un travail avec des noms d'opérateurs ne faisant pas partie du standard SQL, vous aurez habituellement besoin de séparer les opérateurs adjacents avec des espaces pour éviter toute ambiguïté. Par exemple, si vous avez défini un opérateur unaire gauche nommé @, vous ne pouvez pas écrire X*@Y ; vous devez écrire X* @Y pour vous assurer que PostgreSQL le lit comme deux noms d'opérateurs, et non pas comme un seul.

4.1.4. Caractères spéciaux

Quelques caractères non alphanumériques ont une signification spéciale, différente de celui d'un opérateur. Les détails sur leur utilisation sont disponibles à l'endroit où l'élément de syntaxe respectif est décrit. Cette section existe seulement pour avertir de leur existence et pour résumer le but de ces caractères.

  • Un signe dollar ($) suivi de chiffres est utilisé pour représenter un paramètre de position dans le corps de la définition d'une fonction ou d'une instruction préparée. Dans d'autres contextes, le signe dollar pourrait faire partie d'un identifiant.

  • Les parenthèses (()) ont leur signification habituelle pour grouper leurs expressions et renforcer la précédence. Dans certains cas, les parenthèses sont requises car faisant partie de la syntaxe fixée d'une commande SQL particulière.

  • Les crochets ([]) sont utilisés pour sélectionner les éléments d'un tableau. Voir la Section 8.10 pour plus d'informations sur les tableaux.

  • Les virgules (,) sont utilisées dans quelques constructions syntaxiques pour séparer les éléments d'une liste.

  • Le point-virgule (;) termine une commande SQL. Il ne peut pas apparaître quelque part dans une commande, sauf à l'intérieur d'une constante de type chaîne ou d'un identifiant entre guillemets.

  • Le caractère deux points (:) est utilisé pour sélectionner des << morceaux >> de tableaux. (Voir la Section 8.10.) Dans certains dialectes SQL (tel que le SQL embarqué), il est utilisé pour préfixer les noms de variable.

  • L'astérisque (*) a une signification spéciale lorsqu'elle est utilisée dans une commande SELECT ou avec une fonction d'agrégat COUNT.

  • Le point (.) est utilisé dans les constantes numériques et pour séparer les noms de schéma, table et colonne.

4.1.5. Commentaires

Un commentaire est une séquence arbitraire de caractères commençant avec deux tirets et s'étendant jusqu'à la fin de la ligne, par exemple :

-- Ceci est un commentaire standard en SQL

Autrement, les blocs de commentaires style C peuvent être utilisés :

/* commentaires multilignes
 * et imbriqués: /* bloc de commentaire imbriqué */
 */

où le commentaire commence avec /* et s'étend jusqu'à l'occurrence de */. Ces blocs de commentaires s'imbriquent, comme spécifié dans le standard SQL mais pas comme dans le langage C. De ce fait, vous pouvez commenter des blocs importants de code pouvant contenir des blocs de commentaires déjà existants.

Un commentaire est supprimé du flux en entrée avant une analyse plus poussée de la syntaxe et est remplacé par un espace blanc.

4.1.6. Précédence lexicale

Le Tableau 4-1 affiche la précédence et l'associativité des opérateurs dans PostgreSQL. La plupart des opérateurs ont la même précédence et sont associatifs par la gauche. La précédence et l'associativité des opérateurs sont codées en dur dans l'analyseur. Ceci pourrait conduire à un comportement non intuitif ; par exemple, les opérateurs booléens < et > ont une précédence différente des opérateurs booléens <= et >=. De même, vous aurez quelque fois besoin d'ajouter des parenthèses lors de l'utilisation de combinaisons d'opérateurs binaires et unaires. Par exemple :

SELECT 5 ! - 6;

sera analysé comme

SELECT 5 ! (- 6);

parce que l'analyseur n'a aucune idée, jusqu'à ce qu'il soit trop tard que ! est défini comme un opérateur suffixe, et non pas préfixe. Pour obtenir le comportement désiré dans ce cas, vous devez écrire :

SELECT (5 !) - 6;

C'est le prix à payer pour l'extensibilité.

Tableau 4-1. Précédence des opérateurs (en ordre décroissant)

Opérateur/ÉlémentAssociativitéDescription
.gaucheséparateur de noms de table et de colonne
::gaucheconversion de type, style PostgreSQL
[ ]gauchesélection d'un élément d'un tableau
-droitenégation unaire
^gaucheexponentiel
* / %gauchemultiplication, division, modulo
+ -gaucheaddition, soustraction
IS IS TRUE, IS FALSE, IS UNKNOWN, IS NULL
ISNULL test pour NULL
NOTNULL test pour non NULL
(autres)gauchetout autre opérateur natif et défini par l'utilisateur
IN appartenance à un ensemble
BETWEEN compris
OVERLAPS surcharge un intervalle de temps
LIKE ILIKE SIMILAR correspondance de modèles de chaînes
< > inférieur, supérieur à
=droiteégalité, affectation
NOTdroitenégation logique
ANDgaucheconjonction logique
ORgauchedisjonction logique

Notez que les règles de précédence des opérateurs s'appliquent aussi aux opérateurs définis par l'utilisateur qui ont le même nom que les opérateurs internes mentionnés ici. Par exemple, si vous définissez un opérateur << + >> pour un type de données personnalisé, il aura la même précédence que l'opérateur interne << + >>, peu importe ce que fait le votre.

Lorsqu'un nom d'opérateur qualifié par un schéma est utilisé dans la syntaxe OPERATOR, comme par exemple dans

SELECT 3 OPERATOR(pg_catalog.+) 4;

la construction OPERATOR est prise pour avoir la précédence par défaut affichée dans le Tableau 4-1 pour les opérateurs << autres >>. Ceci est vrai quelque soit le nom spécifique de l'opérateur apparaissant à l'intérieur de OPERATOR().