Pour bien comprendre le langage SQL, nous allons brièvement exposer les principes sur lesquels repose ce langage (algèbre relationnelle).
Une table (relation) est un ensemble de tuples. On peut donc appliquer à une table les opérateurs algébriques usuels. Le résultat d'une opération ou requête est une nouvelle table qui est exploitable à son tour dans une nouvelle opération. Tous les opérateurs peuvent être dérivés de cinq primitives de base : la projection, la sélection, l'union, la différence et le produit. L'opérateur de jointure qui peut être déduit des cinq primitives de base est cependant fondamental (algèbre relationnelle).
La projection permet de ne conserver que les attributs intéressants d'une table (sélection verticale). De plus, la projection élimine les répétitions de tuples résultant de cette sélection.
La sélection permet de ne conserver que les tuples qui respectent une condition définie sur les valeurs des attributs (sélection horizontale).
L'union réalise l'union de plusieurs tables.
Exemple 2.4. Union
CLIENTS3 = SELECT CLIENTS WHERE cltloc = 'PARIS' UNION SELECT BONSCLIENTS WHERE cltloc='BRUXELLES'
La différence consiste à prendre les tuples appartenant à une table mais pas à une autre.
Le produit réalise la juxtaposition de tous les tuples de la première table avec chaque tuple de la seconde. Celà signifie que, si les deux tables ont respectivement M et N tuples, la table résultante aura M×N tuples. Cette opération présente peu d'intérêt mais combinée avec une sélection, on obtient une opération fondamentale : la jointure.
La jointure n'est possible que sur deux tables possédant un attribut de domaine commun. Elle consiste à juxtaposer les tuples dont la valeur d'un attribut est égal dans les deux tables. C'est une primitive dérivée car elle peut être définie à l'aide des primitives précédentes (exercice laissé au lecteur).
Les primitives peuvent être combinées pour constituer des requêtes plus élaborées. La séquence d'opérateurs permettant de réaliser une requête élaborée devient assez vite complexe. Le langage SQL permet (heureusement) d'exprimer globalement une requête sans faire apparaître les tables et les primitives intermédiaires. Ce sera le moteur SQL qui sera chargé d'optimiser la requête.
Exemple 2.7. Requête
Une requête SQL qui permet de dresser la liste des noms des clients qui ont acheté des articles de moins de 200F est :
SELECT DISTINCT cltnom FROM clients, commandes, ligcommandes, articles WHERE cltnum=cmdclt AND artnum=lcdart AND cmdnum=ldccmd AND artpv < 200Une combinaison de primitives permettant d'exécuter cette requête est :
temp1 = SELECT articles WHERE artpv < 200 temp2 = PROJECT temp1 OVER (artnum) temp3 = PROJECT clients OVER (cltnum,cltnom) temp4 = PROJECT commandes OVER (cmdnum, cmdclt) temp5 = PROJECT ligcommandes OVER (ldccmd,ldcart) temp6 = temp2 JOIN temp5 ON artnum=ldcart temp7 = PROJECT temp6 OVER (ldccmd) temp8 = temp3 JOIN temp4 ON cltnum=cmdclt temp9 = PROJECT temp8 OVER (cltnom, cmdnum) temp10 = temp7 JOIN temp9 ON ldccmd=cmdnum resultat = PROJECT temp10 OVER (cltnom)Une telle séquence n'est, en général, pas unique. La séquence fournie est une des plus efficaces (le lecteur peut s'exercer à en trouver d'autres).