4.2. Expressions de valeurs

Les expressions de valeurs sont utilis�es dans une grande vari�t� de contextes, tels que dans la liste cible d'une commande SELECT, dans les nouvelles valeurs de colonnes d'une commande INSERT ou UPDATE, ou dans les conditions de recherche d'un certain nombre de commandes. Le r�sultat d'une expression de valeurs est quelque fois appel� scalaire, pour le distinguer du r�sultat d'une expression de table (qui est une table). Les expressions de valeurs sont aussi appel�es des expressions scalaires (voire m�me simplement des expressions). La syntaxe d'expression permet le calcul des valeurs � partir de morceaux primitifs en utilisant les op�rations arithm�tiques, logiques, d'ensemble et autres.

Une expression de valeur fait partie des suivantes :

En plus de cette liste, il existe un certain nombre de constructions pouvant �tre class�es comme une expression mais ne suivant aucune r�gle de syntaxe g�n�rale. Elles ont g�n�ralement la s�mantique d'une fonction ou d'un op�rateur et sont expliqu�es � l'emplacement appropri� dans le Chapitre 9. Un exemple est la clause IS NULL.

Nous avons d�j� discut� des constantes dans la Section 4.1.2. Les sections suivantes discutent des options restantes.

4.2.1. R�f�rences de colonnes

Une colonne peut �tre r�f�renc�e avec la forme

correlation.nom_colonne

correlation est le nom d'une table (parfois qualifi� par son nom de sch�ma) ou un alias d'une table d�finie au moyen de la clause FROM ou un des mots cl�s NEW ou OLD. (NEW et OLD peuvent seulement appara�tre dans les r�gles de r��criture alors que les autres noms de corr�lation peuvent �tre utilis�s dans toute instruction SQL.) Le nom de corr�lation et le point de s�paration peuvent �tre omis si le nom de colonne est unique dans les tables utilis�es par la requ�te courante. (Voir aussi Chapitre 7.)

4.2.2. Param�tres de position

Un param�tre de position est utilis� pour indiquer une valeur fournie en externe par une instruction SQL. Les param�tres sont utilis�s dans des d�finitions de fonction SQL et dans les requ�tes pr�par�es. Quelques biblioth�ques clients supportent aussi la sp�cification de valeurs de donn�es s�par�ment de la cha�ne de commande SQL, auquel cas les param�tres sont utilis�s pour r�f�rencer les valeurs de donn�es en dehors. Le format d'une r�f�rence de param�tre est :

$num�ro

Par exemple, consid�rez la d�finition d'une fonction dept comme

CREATE FUNCTION dept(text) RETURNS dept
    AS $$ SELECT * FROM dept WHERE nom = $1 $$
    LANGUAGE SQL;

Ici, $1 sera remplac� par le premier argument de fonction lorsque la commande sera appel�e.

4.2.3. Indices

Si une expression r�cup�re une valeur de type tableau, alors un �l�ment sp�cifique du tableau peut �tre extrait en �crivant

expression[indice]

ou des �l�ments adjacents (un <<�morceau de tableau�>>) peuvent �tre extrait en �crivant

expression[indice_bas:
indice_haut]

(Ici, les crochets [ ] doivent appara�tre litt�ralement.) Chaque indice est lui-m�me une expression, qui doit renvoyer une valeur enti�re.

En g�n�ral, l'expression de type tableau doit �tre entre parenth�ses mais celles-ci peuvent �tre omises lorsque l'expression � indicer est seulement une r�f�rence de colonne ou une position de param�tre. De plus, les indices multiples peuvent �tre concat�n�s lorsque le tableau original est multi-dimensionnel. Par exemple,

matable.colonnetableau[4]
matable.colonnes_deux_d[17][34]
$1[10:42]
(fonctiontableau(a,b))[42]

Les parenth�ses dans ce dernier exemple sont requises. Voir la Section 8.10 pour plus d'informations sur les tableaux.

4.2.4. S�lection de champs

Si une expression r�cup�re une valeur de type compos� (type row), alors un champ sp�cifique de la ligne est extrait en �crivant

expression.nom_champ

En g�n�ral, l'expression de ligne doit �tre entre parenth�ses mais les parenth�ses peuvent �tre omises lorsque l'expression � partir de laquelle se fait la s�lection est seulement une r�f�rence de table ou un param�tre de position. Par exemple,

matable.macolonne
$1.unecolonne
(fonctionligne(a,b)).col3

(Donc, une r�f�rence de colonne qualifi�e est r�ellement un cas sp�cial de syntaxe de s�lection de champ.)

4.2.5. Appels d'op�rateurs

Il existe trois syntaxes possibles pour l'appel d'un op�rateur :

expression op�rateur expression (op�rateur binaire pr�fixe)
op�rateur expression (op�rateur unaire pr�fixe)
expression op�rateur (op�rateur unaire suffixe)

o� le jeton op�rateur suit les r�gles de syntaxe de la Section 4.1.3, ou est un des mots cl�s AND, OR et NOT, ou est un nom d'op�rateur qualifi� de la forme

OPERATOR(schema.nom_operateur)

Quel op�rateur particulier existe et est-il unaire ou binaire d�pend des op�rateurs d�finis par le syst�me ou l'utilisateur. Le Chapitre 9 d�crit les op�rateurs internes.

4.2.6. Appels de fonctions

La syntaxe pour un appel de fonction est le nom d'une fonction (qualifi� ou non du nom du sch�ma) suivi par sa liste d'arguments entre parenth�ses :

fonction
([expression [,
expression ... ]] )

Par exemple, ce qui suit calcule la racine carr� de 2 :

sqrt(2)

La liste des fonctions int�gr�es est dans le Chapitre 9. D'autres fonctions pourraient �tre ajout�es par l'utilisateur.

4.2.7. Expressions d'agr�gat

Une expression d'agr�gat repr�sente l'application d'une fonction d'agr�gat � travers les lignes s�lectionn�es par une requ�te. Une fonction d'agr�gat r�duit les nombres entr�s en une seule valeur de sortie, comme la somme ou la moyenne des valeurs en entr�e. La syntaxe d'une expression d'agr�gat est une des suivantes :

nom_agregat (expression)
nom_agregat (ALL
expression)
nom_agregat (DISTINCT
expression)
nom_agregat ( * )

o� nom_agregat est un agr�gat pr�c�demment d�fini (parfois qualifi� d'un nom de sch�ma) et expression est toute expression de valeur qui ne contient pas lui-m�me une expression d'agr�gat.

La premi�re forme d'expression d'agr�gat appelle l'agr�gat pour toutes les lignes en entr�e pour lesquelles l'expression donn�e ne trouve pas une valeur NULL. (En fait, c'est � la fonction d'agr�gat de savoir si elle doit ignorer ou non les valeurs NULL... mais toutes les fonctions standards le font.) La seconde forme est identique � la premi�re car ALL est par d�faut. La troisi�me forme implique l'agr�gat pour toutes les valeurs de l'expression non NULL et distinctes trouv�es dans les lignes en entr�e. La derni�re forme appelle l'agr�gat une fois pour chaque ligne en entr�e qu'elle soit NULL ou non ; comme aucune valeur particuli�re en entr�e n'est sp�cifi�e, c'est g�n�ralement utile pour la fonction d'agr�gat count().

Par exemple, count(*) trouve le nombre total de lignes en entr�e ; count(f1) r�cup�re le nombre de lignes en entr�e pour lesquelles f1 n'est pas NULL ; count(distinct f1) retrouve le nombre de valeurs distinctes non NULL de f1.

Les fonctions d'agr�gat pr�d�finies sont d�crites dans la Section 9.15. D'autres fonctions d'agr�gat pourraient �tre ajout�es par l'utilisateur.

Une expression d'agr�gat pourrait appara�tre dans la liste de r�sultat ou dans la clause HAVING d'une commande SELECT. Elle est interdite dans d'autres clauses, telles que WHERE, parce que ces clauses sont logiquement �valu�es avant que les r�sultats des agr�gats soient form�s.

Lorsqu'une expression d'agr�gat appara�t dans une sous-requ�te (voir la Section 4.2.9 et la Section 9.16), l'agr�gat est normalement �valu� sur les lignes de la sous-requ�te. Mais, une exception arrive si l'argument de l'agr�gat contient seulement des niveaux externes de variables : ensuite, l'agr�gat appartient au niveau externe le plus proche et est �valu� sur les lignes de cette requ�te. L'expression de l'agr�gat en un tout est une r�f�rence externe pour la sous-requ�te dans laquelle il appara�t et agit comme une constante sur toute �valuation de cette requ�te. La restriction apparaissant seulement dans la liste de r�sultat ou dans la clause HAVING s'applique avec respect du niveau de requ�te auquel appartient l'agr�gat.

4.2.8. Conversions de type

Une conversion de type sp�cifie une conversion � partir d'un type de donn�es en un autre. PostgreSQL accepte deux syntaxes �quivalentes pour les conversions de type :

CAST ( expression AS type )
expression::type

La syntaxe CAST est conforme � SQL ; la syntaxe avec :: est historique dans PostgreSQL usage.

Lorsqu'une conversion est appliqu�e � une expression de valeur pour un type connu, il repr�sente une conversion de type � l'ex�cution. Cette conversion r�ussira seulement si une op�ration convenable de conversion de type a �t� d�finie. Notez que ceci est subtilement diff�rent de l'utilisation de conversion avec des constantes, comme indiqu� dans la Section 4.1.2.5. Une conversion appliqu�e � une cha�ne litt�rale repr�sente l'affectation initiale d'un type pour une valeur constante litt�rale, et donc cela r�ussira pour tout type (si le contenu de la cha�ne litt�rale est une syntaxe accept�e en entr�e pour le type de donn�e).

Une conversion de type explicite pourrait �tre habituellement omise s'il n'y a pas d'ambigu�t� sur le type qu'une expression de valeur pourrait produire (par exemple, lorsqu'elle est affect�e � une colonne de table) ; le syst�me appliquera automatiquement une conversion de type dans de tels cas. N�anmoins, la conversion automatique est r�alis�e seulement pour les conversions marqu�es <<�OK pour application implicite�>> dans les catalogues syst�me. D'autres conversions peuvent �tre appel�es avec la syntaxe de conversion explicite. Cette restriction a pour but d'emp�cher l'application silencieuse de conversions surprenantes.

Il est aussi possible de sp�cifier une conversion de type en utilisant une syntaxe de type fonction :

nom_type ( expression )

N�anmoins, ceci fonctionne seulement pour les types dont les noms sont aussi valides en tant que noms de fonctions. Par exemple, double precision ne peut pas �tre utilis� de cette fa�on mais son �quivalent float8 le peut. De m�me, les noms interval, time et timestamp peuvent seulement �tre utilis�s de cette fa�on s'ils sont entre des guillemets doubles � cause des conflits de syntaxe. Du coup, l'utilisation de la syntaxe de conversion du style fonction am�ne � des inconsistances et devrait probablement �tre �vit�e dans les nouvelles applications. (La syntaxe style fonction est en fait seulement un appel de fonction. Quand un des deux standards de syntaxe de conversion est utilis� pour faire une conversion � l'ex�cution, elle appellera en interne une fonction enregistr�e pour r�aliser la conversion. Par convention, ces fonctions de conversion ont le m�me nom que leur type de sortie et, du coup, la <<�syntaxe style fonction�>> n'est rien de plus qu'un appel direct � la fonction de conversion sous-jacente. �videmment, une application portable ne devrait pas s'y fier.)

4.2.9. Sous-requ�tes scalaires

Une sous-requ�te scalaire est une requ�te SELECT ordinaire entre parenth�ses renvoyant exactement une ligne avec une colonne. (Voir le Chapitre 7 pour plus d'informations sur l'�criture des requ�tes.) La requ�te SELECT est ex�cut�e et la seule valeur renvoy�e est utilis�e dans l'expression de valeur englobante. C'est une erreur d'utiliser une requ�te qui renvoie plus d'une ligne ou plus d'une colonne comme requ�te scalaire. (Mais si, lors d'une ex�cution particuli�re, la sous-requ�te ne renvoie pas de lignes, alors il n'y a pas d'erreur ; le r�sultat scalaire est suppos� NULL.) La sous-requ�te peut r�f�rencer des variables de la requ�te englobante, qui agiront comme des constantes durant toute �valuation de la sous-requ�te. Voir aussi Section 9.16 pour d'autres expressions impliquant des sous-requ�tes.

Par exemple, ce qui suit trouve la ville disposant de la population la plus importante dans chaque �tat :

SELECT nom, (SELECT max(pop) FROM villes WHERE villes.etat = etat.nom)
    FROM etats;

4.2.10. Constructeurs de tableaux

Un constructeur de tableau est une expression qui construit une valeur de tableau � partir de valeurs de ses membres. Un constructeur de tableau simple utilise le mot cl� ARRAY, un crochet ouvrant [, une ou plusieurs expressions (s�par�es par des virgules) pour les valeurs des �l�ments du tableau et finalement un crochet fermant ]. Par exemple :

SELECT ARRAY[1,2,3+4];
  array
---------
 {1,2,7}
(1 row)

Le type d'�l�ment du tableau est le type commun des expressions des membres, d�termin� en utilisant les m�mes r�gles que pour les constructions UNION ou CASE (voir Section 10.5).

Les valeurs de tableaux multidimensionnels peuvent �tre construits par des constructeurs de tableaux imbriqu�s. Pour les constructeurs internes, le mot cl� ARRAY pourrait �tre omis. Par exemple, ces expressions produisent le m�me r�sultat :

SELECT ARRAY[ARRAY[1,2], ARRAY[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

SELECT ARRAY[[1,2],[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

Comme les tableaux multidimensionnels doivent �tre rectangulaires, les constructeurs internes du m�me niveau doivent produire des sous-tableaux de dimensions identiques.

Les �l�ments d'un constructeur de tableau multidimensionnel peuvent �tre tout ce qui r�cup�re un tableau du bon type, pas seulement une construction de sous-ARRAY. Par exemple :

CREATE TABLE arr(f1 int[], f2 int[]);

INSERT INTO arr VALUES (ARRAY[[1,2],[3,4]], ARRAY[[5,6],[7,8]]);

SELECT ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] FROM arr;
                     array
------------------------------------------------
 {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}}
(1 row)

Il est aussi possible de construire un tableau � partir des r�sultats d'une sous-requ�te. Avec cette forme, le constructeur de tableau est �crit avec le mot cl� ARRAY suivi par une sous-requ�te entre parenth�ses (et non pas des crochets). Par exemple :

SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%');
                          ?column?
-------------------------------------------------------------
 {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31}
(1 row)

La sous-requ�te doit renvoyer une seule colonne. Le tableau � une dimension r�sultant aura un �l�ment pour chaque ligne dans le r�sultat de la sous-requ�te, avec un type �l�ment correspondant � celui de la colonne en sortie de la sous-requ�te.

Les indices d'une valeur de tableau construit avec ARRAY commencent toujours � un. Pour plus d'informations sur les tableaux, voir la Section 8.10.

4.2.11. Constructeurs de lignes

Un constructeur de ligne est une expression qui construit une valeur de ligne (aussi appel�e une valeur composite) � partir des valeurs de ses membres. Un constructeur de ligne consiste en un mot cl� ROW, une parenth�se gauche, z�ro ou plus d'une expression (s�par�es par des virgules) pour les valeurs des champs de la ligne, et finalement une parenth�se droite. Par exemple,

        SELECT ROW(1,2.5,'ceci est un test');
      

Le mot cl� ROW est optionnel lorsqu'il y a plus d'une expression dans la liste.

Par d�faut, la valeur cr��e par une expression ROW est d'un type d'enregistrement anonyme. Si n�cessaire, il peut �tre converti en un type composite nomm� — soit le type de ligne d'une table soit un type composite cr�� avec CREATE TYPE AS. Une conversion explicite pourrait �tre n�cessaire pour �viter une ambigu�t�. Par exemple :

  CREATE TABLE matable(f1 int, f2 float, f3 text);

  CREATE FUNCTION recup_f1(matable) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

  -- Aucune conversion n�cessaire parce que seul un recup_f1() existe
  SELECT recup_f1(ROW(1,2.5,'ceci est un test'));
  recup_f1
  --------
  1
  (1 row)

  CREATE TYPE montypeligne AS (f1 int, f2 text, f3 numeric);

  CREATE FUNCTION recup_f1(montypeligne) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

  -- Maintenant, nous avons besoin d'une conversion pour indiquer la fonction � appeler:
  SELECT recup_f1(ROW(1,2.5,'ceci est un test'));
  ERROR:  function recup_f1(record) is not unique

  SELECT recup_f1(ROW(1,2.5,'ceci est un test')::matable);
  getf1
  -------
  1
  (1 row)

  SELECT recup_f1(CAST(ROW(11,'ceci est un test',2.5) AS montypeligne));
  getf1
  -------
  11
  (1 row)

Les constructeurs de lignes peuvent �tre utilis�s pour construire des valeurs composites � stocker dans une colonne de table de type composite ou pour �tre pass� � un fonction qui accepte un param�tre composite. De plus, il est possible de comparer deux valeurs de lignes ou pour tester une ligne avec IS NULL ou IS NOT NULL, par exemple

  SELECT ROW(1,2.5,'ceci est un test') = ROW(1, 3, 'pas le m�me');
  
  SELECT ROW(a, b, c) IS NOT NULL FROM table;

Pour plus de d�tails, voir Section 9.17. Les constructeurs de lignes peuvent aussi �tre utilis�s en connexion avec des sous-requ�tes, comme discut� dans Section 9.16.

4.2.12. R�gles d'�valuation des expressions

L'ordre d'�valuation des sous-expressions n'est pas d�fini. En particulier, les entr�es d'un op�rateur ou d'une fonction ne sont pas n�cessairement �valu�es de la gauche vers la droite ou dans un autre ordre fix�.

De plus, si le r�sultat d'une expression peut �tre d�termin� par l'�valuation de quelques parties de celui-ci, alors d'autres sous-expressions devraient ne pas �tre �valu�es du tout. Par exemple, si vous �crivez :

SELECT true OR une_fonction();

alors une_fonction() pourrait (probablement) ne pas �tre appel�e du tout. Pareil dans le cas suivant :

SELECT somefunc() OR true;

Notez que ceci n'est pas identique au <<�court-circuitage�>> de gauche � droite des op�rateurs bool�ens utilis� par certains langages de programmation.

En cons�quence, il est d�conseill� d'utiliser des fonctions ayant des effets de bord dans une partie des expressions complexes. Il est particuli�rement dangereux de se fier aux effets de bord ou � l'ordre d'�valuation dans les clauses WHERE et HAVING, car ces clauses sont reproduites de nombreuses fois lors du d�veloppement du plan d'ex�cution. Les expressions bool�ennes (combinaisons AND/OR/NOT) dans ces clauses pourraient �tre r�organis�es de toute autre fa�on que celles autoris�es dans l'alg�bre bool�enne.

Quand il est essentiel de forcer l'ordre d'�valuation, une construction CASE (voir Section 9.13) pourrait �tre utilis�e. Par exemple, c'est une fa�on, non s�re, d'essayer d'�viter une division par z�ro dans une clause WHERE :

SELECT ... WHERE x <> 0 AND y/x > 1.5;

Mais ceci est s�r :

SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END;

Une construction CASE utilis�e de cette fa�on d�jouera les tentatives d'optimisation, donc cela ne sera fait que si n�cessaire. (Dans cet exemple particulier, il serait sans doute mieux de contourner le probl�me en �crivant y > 1.5*x.)