SQL3. La commande SELECT et les fonctions SQL
Dans le précédent article nous avons vu
l’historique de SQL et ses différentes composantes. Nous entrons
maintenant dans le vif du sujet, en nous intéressant au simple SELECT. Préambule 1. La commande SELECT 1.1. L'opérateur * (étoile) 1.2. L'opérateur DISTINCT (ou ALL) 1.3. L'opérateur AS 1.4. Opérateur de concaténation 1.5. Opérateurs mathématiques de base 1.6. Particularité du "FROM" 1.7. Utilisation du caractère double quote (guillemet) 2. La clause ORDER BY 3. La clause WHERE 3.1. Opérateurs de comparaison 3.2. Opérateur IN 3.3. Opérateur BETWEEN 3.4. Opérateur LIKE 3.5. Résumé des opérateurs pour les prédicats de la clause WHERE 4. Fonctions diverses 4.1. Trantypage à l'aide de la fonction CAST 4.2. Mise en majuscule / Minuscule 4.3. Supprimer les blancs (ou tout autre caractères) 4.4. Extraire une sous chaîne 4.5. Opérateur de traitement des dates 4.5.1. Extraire un paramètre temporel d'une date 4.5.2. Heure et date courante 4.6. Opérateurs statistiques 4.7. Autres fonctions normalisées 4.8. Autres opérateurs mathématiques (non normalisés) 4.9. Autres opérateurs de traitement des chaînes de caractères (non normalisés) 4.10. Autres opérateurs sur les valeurs temporelles (non normalisés) 4.11. Opérateurs d'ensemble (non normalisés) 5. Traitement des "valeurs" nulles 5.1. Le null n'est ni la chaîne vide, ni le zéro 5.2. Opérateurs de traitement des marqueurs NULL 6. Négation de valeurs 7. Les branchements dans le SQL 7.1. CASE sur expression 7.2. CASE généralisé 8. Le constructeur de lignes valuées (ROW VALUE CONSTRUCTOR) 9. Résumé 10. Conclusion PréambuleNOTA : La structure de la base de
données exemple, ainsi qu'une version des principales bases utilisées
sont disponibles dans la page "La base de données exemple". 1. La commande SELECTLe SELECT est la commande de base du SQL destinée à extraire des données d’une base ou calculer de nouvelles données à partir d’existantes... Voici la syntaxe générale d'une commande SELECT :
NOTA : dans cette syntaxe, les mots
clef du SQL sont en gras, les paramètres en minuscule et entre crochets
on trouve les parties optionnelles En fait l'ordre SQL SELECT est composé de 6 clauses dont 4 sont optionnelles. Clauses de l'ordre SELECT :
NOTA : La plupart du temps, la
difficulté réside dans la compréhension de la différence entre le filtre
WHERE et le filtre HAVING. Disons plus pragmatiquement que le filtre
WHERE permet de filtrer les données des tables tandis que le filtre
HAVING permet de filtrer les données du résultat... REMARQUE : pour spécifier une valeur littérale il faut l'entourer de guillemets simples. Un premier exemple basique : Exemple 1
Permet de trouver les noms et prénoms des clients dont le titre est ‘M.’ (monsieur). NOTA : comme tous les paramètres à
prendre sous forme de littéraux doivent être exprimés entourés
d'apostrophes (simple côtes), il faut dédoubler un tel caractère s'il
s'avère présent dans la chaîne utilisé. 1.1. L'opérateur * (étoile)Le caractère * (étoile) récupère toutes les colonnes de la table précisée dans la clause FROM de la requête. Juste après le mot clef SELECT, on précise les colonnes de la table qui doivent être présentées dans la réponse. L’utilisation du caractère étoile ramène toutes les colonnes de la table dans la réponse. Dans le cas contraire il faut expressément nommer chacune des colonnes et les séparer par des virgules. Exemple 2
Notons tout de suite la présence à
plusieurs reprises du mot clef "NULL" dans la cologne CLI_ENSEIGNE. Non
il ne s'agit pas d'une enseigne particulière, mais simplement de
l'absence d'information. Nous verrons que l'absence d'information, c'est
le marquer "NULL" qui différe de la chaîne de caractère vierge ("") ou
encore du zéro. 1.2. L'opérateur DISTINCT (ou ALL)Lorsque le moteur construit la réponse, il
rapatrie toutes les lignes correspondantes, généralement dans l’ordre
ou il les trouve, même si ces dernières sont en double, c'est à dire
qu'il récupère toutes les lignes (ALL par défaut). C’est pourquoi il est
souvent nécessaire d’utiliser le mot clef DISTINCT qui permet d‘éliminer les doublons dans la réponse. Exemples 3 et 4
1.3. L'opérateur ASVous pouvez rajouter autant de colonnes que vous le désirez en utilisant le mot clef AS. En principe l’opérateur AS sert à donner un nom à de nouvelles colonnes créées par la requête. Exemple 5
1.4. Opérateur de concaténationL'opérateur || (double barre verticale) permet de concaténer des champs de type caractères. Exemple 6
Néanmoins on trouve dans certains SGBDR le + comme opérateur de concaténation, comme la fonction CONCAT. 1.5. Opérateurs mathématiques de baseOn, peut utiliser les opérateurs mathématiques de base pour combiner différentes colonnes (,+,-, *, /,). Exemple 7
1.6. Particularité du "FROM"Il est possible de surnommer une table
dans la clause FROM, dans ce cas, la syntaxe de la partie FROM de la
commande SELECT est la suivante :
Nous verrons dans quel cas ce renom est nécessaire ou obligatoire. NOTA : certains auteurs préfèrent utiliser le mot d'alias que nous rejetons car il indique souvent un autre concept, ou de synonyme, que nous acceptons de manière timorée... 1.7. Utilisation du caractère double quote (guillemet)Lorsqu’un nom d’un élément d’une base de
données (table, colonne par exemple) est identique à un mot clef du SQL,
il convient de l’entourer de guillemets (double quote). En principe,
les mots réservés du SQL sont déconseillés pour nommer des objets du
modèle physique de données... Imaginons une table de nom JOIN, composée des champs suivants : NOM SELECT DATE NOT ------- ------ ------- --- DURAND Oui 1999-11-12 F DUVAL Non 1998-01-17 M Exemple 8 : nous désirons sélectionner les colonnes SELECT et DATE lorsque la colonne NOT vaut F...
Cela est aussi nécessaire lorsque le nom
(d'une colonne ou d'une table) est composé de caractères particuliers
tels que les blancs ou autres, ce qui est à éviter. REMARQUE : les noms des identifiants d'objet de base de données doivent être écrit dans le jeux de caractères restreint suivant : [A..Z] + [a..z] + [0..9] + [ _ ]. Ils ne doivent pas commencer par un chiffre et sont insensibles à la casse (indifférence entre majuscule et minuscule). 2. La clause ORDER BY
Cette clause permet de définir le tri des
colonnes de la réponse, soit en précisant le nom littéral de la colonne,
soit en précisant son n° d'ordre dans l'énumération qui suit le mot
clef SELECT. ASC spécifie l’ordre ascendant et DESC l’ordre descendant du tri. ASC ou DESC peut être omis, dans ce cas c'est l'ordre ascendant qui est utilisé par défaut. Bien que la clause ORDER BY ne soit pas
nécessaire, il est souvent utile de trier la réponse en fonction des
colonnes. En revanche le temps de réponse s'en ressent souvent. Pour spécifier l'ordre de tri, on doit placer les noms des colonnes séparées par des virgules juste après le mot clef "ORDER BY", dans l'ordre voulu.. On peut aussi utiliser le rang de chaque colonne dans l'ordre spécifié dans la clause SELECT. Attention : le tri est un tri
interne, il ne faut donc placer dans cette clause que les noms des
colonnes présentées dans la clause SELECT. Souvent, le fait de placer DISTINCT suffit,
en général, à établir un tri puisque le moteur doit se livrer à une
comparaison des lignes mais ce mécanisme n'est pas garanti car ce tri
s’effectue dans un ordre non contrôlable qui peut varier d’un serveur à
l’autre. Exemple 9
REMARQUE : les marqueurs NULL sont situés en premier dans l'ordre ainsi établi. NOTA : Un problème, qui n’est pas
résolu, est de pouvoir choisir l’ordre des colonnes de la réponse. Sur
certains serveurs cela peut être obtenu en plaçant les noms des colonnes
à obtenir dans l’ordre où l’on veut les voir apparaître dans la clause
SELECT, mais cette possibilité n'est jamais garantie... ATTENTION : la clause ORDER BY est
la dernière clause de tout ordre SQL et ne doit figurer qu'une seule
fois dans le SELECT, même s'i l existe des requêtes imbriquées ou un jeu
de requêtes ensemblistes. 3. La clause WHERE
Le prédicat doit contenir n’importe quelle expression logique renvoyant une valeur vrai. Ainsi, une requête aussi stupide que la suivante, est supposée fonctionner : Exemple 10
Attention : la plupart des SGBDR ne comportent pas de colonne de type booléen. Une requête comme la première risque d'échouer. Exemple 11
Pour palier au manque de booléen, on
utilise soit un littéral (True/False, Vrai/Faux, Oui/Non), soit un
numérique avec les valeurs 0 (Faux) et 1 (Vrai). L'avantage des valeurs
numériques est que le calcul logique est comparable aux divisions et
additions...
similitude entre le ET et la multiplication
similitude entre le OU et l'addition
3.1. Opérateurs de comparaisonDans la clause WHERE, vous disposez de différents opérateurs de comparaisons logiques :
Exemple 12
Ici on obtient tous les noms et prénoms des clients dont le nom commence par les lettres A, B, C ou D. Attention : dans certains moteurs de requête SQL l’opérateur « différent de » (<>) s’écrit != 3.2. Opérateur INL'opérateur IN permet de rechercher
si une valeur se trouve dans un ensemble donné, quel que soit le type
des valeurs de référence spécifiées (alpha, numérique, date…). Bien
entendu, il est possible d’inverser le fonctionnement de l’opérateur IN
en lui adjoignant l’opérateur NOT. Exemple 13
On recherche les clients de sexe féminin, basés sur le code titre. Le contenu de la parenthèse peut être
remplacé par le resultat d'une requête possédant une colonne unique.
Dans ce cas on parle de requêtes imbriquées, ce que nous verrons plus
loin. 3.3. Opérateur BETWEENL'opérateur BETWEEN permet de rechercher
si une valeur se trouve dans un intervalle donné, quel que soit le type
des valeurs de référence spécifiées (alpha, numérique, date...). Ainsi, la requête vue dans l'exemple 12 peut s'écrire : Exemple 14
NOTA : les opérateurs IN et BETWEEN
sont très pratiques dans le cas où l’on désire effectuer des requêtes
où l’utilisateur peut saisir une liste de choix multiples (IN) ou une
plage de valeur (BETWEEN). 3.4. Opérateur LIKEL'opérateur LIKE permet d’effectuer une
comparaison partielle. Il est surtout employé avec les colonnes
contenant des données de type alpha. Il utilise les jokers % et _ (‘pour
cent’ et ‘blanc souligné’). Le joker % remplace n'importe quelle chaîne
de caractères, y compris la chaîne vide. Le blanc souligné remplace un
et un seul caractère. Exemple 15
On recherche les clients dont le nom commence par B. Mais si vos données sont susceptibles de
contenir un des deux caractères joker, alors il faut recourir à une
séquence d’échappement, à l’aide du mot clef ESCAPE... Cherchons les clients dont l'enseigne contient au moins un caractère blanc souligné : Exemple 16
Pour traiter ce cas, on défini « # » comme
caractère d’échappement. Le caractère qui suit ce caractère
d’échappement est donc interprété comme un caractère et non comme un
joker. NOTA : l’opérateur LIKE effectue une
recherche en tenant compte de la différence entre lettres majuscules et
minuscules. Si vous voulez effectuer une recherche en ne tenant
aucunement compte de la différence entre majuscules et minuscules, il
convient d’utiliser les opérateurs LOWER et UPPER (voir ci dessous).
Mais la plupart du temps, l'utilisation du like dans un SGBDR donné
ignore la casse. 3.5. Résumé des opérateurs pour les prédicats de la clause WHEREVoici une tableau résumant les principaux opérateurs utilisés pour la construction des prédicats :
4. Fonctions diverses4.1. Trantypage à l'aide de la fonction CASTIl permet de changer le type de données
d'une colonne afin d’effectuer une comparaison de données de type
hétérogène par exemple entre un champ contenant des données numériques
et un champ contenant des données de type chaîne de caractères... Sa syntaxe est CAST(colonne AS nouveau type). Exemple 17
L’opérateur CAST permet de transtyper les valeurs contenues dans une colonne. Bien entendu il faut qu'un type de donnée puisse être converti dans un autre type (compatibilité de types) afin que la réponse ne soit pas entaché d'erreurs ou d'omissions. Exemple 18
4.2. Mise en majuscule / MinusculeLes opérateurs LOWER et UPPER permettent de mettre en majuscule ou en minuscule des chaînes de caractères dans les requêtes. Exemple 19
NOTA : pour effectuer une recherche
en ne tenant aucunement compte de la différence entre majuscules et
minuscules, il faut utiliser l’opérateur UPPER (ou lower mais attention à
la transformation des accents !) : Exemple 20
NOTA : certains SGBDR permettent de
paramétrer l'activation de la recherche systématique des chaînes de
caractères sans tenir compte de la casse. Sur d'autres, le paramétrage
permet de confondre les lettres accentuées ou non... 4.3. Supprimer les blancs (ou tout autre caractères)La fonction TRIM permet de supprimer en tête ou en queue (ou les deux) le blanc ou tout autre caractère spécifié.
LEADING : suppression en tête TRAILING : suppression en queue BOTH : suppression en tête et en queue Dans notre table téléphone, nous voulons
supprimer le zéro de tête des n° afin de pouvoir les communiquer aux
étrangers qui n’ont pas besoin de composer ce chiffre (ils doivent
simplement composer le 00 33 suivi du numéro à 9 chiffres). Exemple 21
NOTA : certains serveurs SQL
proposent différentes fonctions comme LTRIM et RTRIM pour une
suppression des blancs en tête ou en queue. 4.4. Extraire une sous chaîneLa fonction SUBSTRING permet
d’extraire une sous chaîne d’une chaîne de caractère. Elle a besoin de
l’ordre du premier caractère et du nombre de caractères sur lequel elle
doit opérer.
Extrait la sous chaîne de nom de colonne en commençant à n sur m caractères. Exemple 22
Cet exemple construit les initiales des clients à partir des colonnes CLI_NOM et CLI_PRENOM_CLI. Attention, certains SGBDR utilisent la fonction SUBSTR. 4.5. Opérateur de traitement des dates4.5.1. Extraire un paramètre temporel d'une dateL’opérateur EXTRACT permet d’extraire depuis une date, le jour le mois ou l’année…
Dans la table des réservation on
recherche l'identifiant des chambres ayant été réservées au cours du
mois de mai de n'importe quelle année et pour 3 personnes. Exemple 23
NOTA : il est dommage de constater que la
fonction EXTRACT du standard SQL, souvent fort utile, est rarement
présente dans les moteurs de bases de données. Ni Access, ni Oracle, ni
Sybase, ni SQL Server en sont dotés. Seul le middleware BDE de Borland
Inprise Corel permet d'exploiter pleinement cette fonction avec les
SGBDR Paradox, dBase, FoxPro, InterBase, MSSQL, Sybase, Informix, DB2,
Oracle. Cependant il est courant de trouver des fonctions s'en approchant : Exemple DATEPART dans SQL Server. 4.5.2. Heure et date couranteL’heure courante, la date courante et le
combiné date/heure courant peuvent être obtenu à l’aide des fonctions
CURRENT_DATE, CURRENT_TIME et CURRENT_TIMESTAMP. Exemple 24
Cette requête renvoie les chambres réservées pour 3 personnes entre la date du jour et pour les deux semaines à venir. Attention : la plupart des SGBDR
n'acceptent pas encore cette version normalisée des fonctions de
recherche de temps courant. Voici les fonctions spécifiques aux
différents serveurs SQL :
4.6. Opérateurs statistiquesIl est possible de réaliser des comptages statistiques sur les colonnes, à l'aide des opérateurs AVG (moyenne), MAX (maximum), MIN (minimum), SUM (total), COUNT (nombre). On les appelent aussi fonctions d'aggrégations. Exemple 25
Cette requête calcule la moyenne, le
montant maximum, minimum, la totalisation et le nombre des tarifs de
chambre pour la date de debut du premier janvier 2001. On peut s'étonner que les opérateurs statistiques VARIANCE ou STDDEV
(écart type) soient rarement présents dans les SGBDR car il s'agit de
fonctions statistiques qui possèdent une grande utilité. Mais la norme
SQL 92 ne les a pas retenu. Cependant, ils existent notamment dans
Oracle. Cela est d'autant plus étonnant que les techniques modernes du
DataWareHouse et en particulier le DataMining, utilisent ces fonctions
dans le cadres de calculs statistiques d'hypercubes (techniques OLAP et
ROLAP). ATTENTION : nous verrons que
l'utilisation des fonctions statistiques nécessite la plupart du temps
la mise en place d'une clause de groupage, afin de déterminé quel est le
sous ensemble cible d'agrégation pour les calculs. 4.7. Autres fonctions normalisées
4.8. Autres opérateurs mathématiques (non normalisés)Les opérateurs ci dessous peuvent être implémentés dans différents moteurs.
Certains sont rarement implémentés du fait
que les SGBDR sont axés sur l’informatique de gestion, la collecte et
le traitement d’informations et non le calcul mathématique. Attention : le nom de certains de ces opérateurs peut différer d’un SGBDR à l’autre. 4.9. Autres opérateurs de traitement des chaînes de caractères (non normalisés)
Attention : le nom de certains de ces opérateurs peut différer d’un SGBDR à l’autre. 4.10. Autres opérateurs sur les valeurs temporelles (non normalisés)
4.11. Opérateurs d'ensemble (non normalisés)
5. Traitement des "valeurs" nullesNOTA : le NULL n'est pas à proprement parler une valeur, mais bien l'absence de valeur, c'est pourquoi nous parlerons de marqueur NULL et non de valeur NULL. Le marqueur NULL pose une quantité de problèmes et nous allons dans ce paragraphe soulever un coin du voile, que nous traiterons un peu plus tard dans le cas général de la recherche des occurrences d’inexistence. 5.1. Le null n'est ni la chaîne vide, ni le zéroNULL n'est pas une valeur. C'est un marqueur. Par conséquent le marqueur NULL ne peut jamais être comparé a une valeur. Recherchons les clients qui n'ont pas d'enseigne. Exemple 26
La réponse doit produire une table vide ! Pour controurner ce problème il faut : soit penser à enregistrer une chaîne de caractère vide lors de l'insertion des données dans la table soit la clause WHERE avec un opérateur spécialisé dans le traitement des valeurs nulles Le problème des « null » a été bien décrit
dans le livre de Joe Celko intitulé « SQL avancé » publié par Thomson
International Publishing. Joe Celko pose la question en ces termes :
l’absence d’information est-elle due à son ignorance ou à son
impertinence ? Pourquoi donc ne pas faire de différence entre la couleur
du toit d’une voiture qui n’est pas connue, et la couleur du toit d’une
moto qui n’est pas applicable… Certains logiciens de l’algèbre
relationnel sont même allés plus loin en proposant différentes valeurs
pour gérer les différents cas, en distinguant des cas très différents :
le « null », le « inconnu » et le « inapplicable »... Il y a donc un véritable dilemme à
utiliser des requêtes en se basant sur des critères d’absence de valeur
et il faut toujours faire très attention aux clauses qui utilisent des
références aux valeurs nulles, suivant ce que l’on veut obtenir.
D’autant plus que les NULL se propagent dans les calculs. Voici un extrait de la table T_LIGNE_FACTURE LIF_ID FAC_ID LIF_QTE LIF_REMISE_POURCENT LIF_REMISE_MONTANT LIF_MONTANT LIF_TAUX_TVA -------- -------- --------- ------------------- ------------------ ----------- ------------ 1 1 1,00 15,00 NULL 320,00 F 18,60 2 3 1,00 NULL 50,00 F 250,00 F 18,60 3 3 1,00 NULL 50,00 F 320,00 F 18,60 4 3 1,00 NULL 50,00 F 240,00 F 18,60 5 5 1,00 NULL NULL 320,00 F 18,60 6 5 1,00 NULL NULL 220,00 F 18,60 7 7 1,00 NULL NULL 220,00 F 18,60 8 7 1,00 NULL NULL 250,00 F 18,60 9 7 1,00 NULL NULL 320,00 F 18,60 10 7 1,00 NULL NULL 270,00 F 18,60 ... Nous voulons calculer le montant total de chacune des lignes de cette table, pour une facture donnée. La requête pour FAC_ID = 3 est la suivante : Exemple 27
On constate que pour les lignes qui n'ont
pas de valeurs renseignées dans les colonnes LIF_REMISE_POURCENT,
LIF_REMISE_MONTANT, le résultat du calcul donne la valeur « null » qui
se traduit à l'affichage par... rien ! NOTA : en général, pour se sortir
de ce mauvais pas, on peut, lors de la création de la base de données,
obliger tous les champs de type numérique (réels ou entiers) a ne pas
accepter la valeur nulle et prendre par défaut la valeur zéro... Attention : l’arithmétique des nuls
est assez particulière... Souvenez vous toujours que les NULL se
propagent. Cela est vrai pour les numériques, les dates mais aussi pour
les chaînes de caractères. Ainsi SQL opère une distinction entre une
chaîne de caractère vide et un champ non renseigné. Dans le cas de la
concaténation d’une colonne NULL et d’une colonne proprement renseigné,
la valeur renvoyée sera NULL !!! 5.2. Opérateurs de traitement des marqueurs NULLLa norme SQL 2 (1992) spécifie une comparaison et différents opérateurs sur les marqueurs NULL : IS NULL / IS NOT NULL : teste si la colonne est vide ou non vide. COALESCE() qui recherche la première valeur non vide dans un ensemble NULLIF NULLifie une colonne en fonction d'une valeur donnée
NOTA : ISNULL (en un seul
mot) est une autre fonction de branchement que l'on rencontre parfois
(renvoi une valeur si la valeur est nulle). Dans la même veine, NVL ou VALUE sont des expressions équivalentes à COALESCE que l'on rencontre sur certains SGBDR. La requête précédente s'exprime, à l'aide de l'opérateur ISNULL : Exemple 28
NOTA : En règle générale, dès que
l'on traite des colonnes contenant des valeurs monétaires ou numériques,
il est bon de faire en sorte que la colonne soit obligatoire et que par
défaut elle soit renseignée à zéro. Sinon, il faudra faire un usage systématique des fonctions NULLIF ou COALESCE dans tous les calculs et cela grèvera les performances d'exécution ! 6. Négation de valeursC'est l'opérateur NOT qui réalise la négation de valeurs et inverse la valeur logique d'un prédicat. L'opérateur NOT peut être combiné avec la plupart des opérateurs de comparaison. Mais il devient très intéressant lorqu'il est combiné aux opérateurs IN, BETWEEN, LIKE et NULL Recherchons par exemple toutes les chambres
permettant de recevoir au moins 3 personnes, ne comportant pas le
chiffre 4 (chiffre de la mort au japon) ni les chambres portant les n° 7
et 13 pour un client particulièrement superstitieux... Exemple 29
Nous verrons que le NOT IN est particulièrement précieux dans les requêtes imbriquées, c'est à dire les requêes multitables. Nous voulons maintenant le nom des clients qui ne commence pas par 'DU' : Exemple 30
7. Les branchements dans le SQLSQL possède un branchement à la manière des IF et autres structures de test des langages procéduraux. Mais il convient de ne l'utiliser qu'a bon escient, c'est à dire aussi peu souvent que possible, beaucoup de cas ouvant être traités soit par le COALESCE soit par des requêtes avec des opérations ensemblistes de type UNION. En effet les performances se dégradent très vite lors de l'usage du CASE à cause de l'impossibilité d'effcetuer des traitements par "paquets". La structure CASE du SQL comprend deux
syntaxes différentes. Le CASE pour branchement sur les valeurs d'une
expression et le CASE généralisé. 7.1. CASE sur expressionDans ce cas, la syntaxe est la suivante :
Exemple 31
7.2. CASE généraliséL'expression disparait au profit de différents prédicats.
Exemple 32
Qui donne le même résultat ! ATTENTION : tous les SGBDR ne supportent pas ces deux syntaxes. NOTA : dans les deux cas il est possible de remplacer le IF d'un langage procédural :
8. Le constructeur de lignes valuées (ROW VALUE CONSTRUCTOR)Nous voici devant un élément peu connu du
SQL car rarement implanté. Rendons hommage à Oracle car il est l'un des
rares SGBDR à l'implémenter. Cette construction peut vous tirer
d'embarras pour bien des cas en simplifiant drastiquement vos requêtes. L'idée consiste à dire que différentes
colonnes devant correspondre à différents critères comparées à l'aide
d'un même opérateur de comparaison peuvent être évaluées simultanément. Il est plus facile de comprendre ce concept à l'aide d'un exemple. Un utilisateur créé une table T_EVENEMENT
dans laquelle il a quatre colonnes indiquant l'heure, la minute, la
seconde de survenance de l'événement et la nature de l'événement :
La question est : quel sont les événements survenus après 3h 10 ? Exemple 33 : intuitivement, nous sommes amenés à écrire la requête suivante :
Mais elle oublie sciement trois événements survenus avant 3h10 ! Comment est-ce possible ? En fait l'événement qui s'est produit à 4h 0 n'est pas pris en compte du fait de la première ligne de la clause WHERE ! EVT_HEURE > 3 AND EVT_MINUTE > 10 tout simplement parce que 0 minute est bien inférieur à 10 minutes ... Or 4h 0 est bien supérieur à 3h 10... il faut donc supprimer la partie AND EVT_MINUTE > 10 de la clause WHERE La bonne construction est donc : Exemple 34
D'où l'idée d'implémenter une construction capable d'évaluer globalement une telle opération. Cette construction est le ROW VALUE CONSTRUCTOR que j'ai traduit par constructeur de lignes valuées... Avec un tel outil, la requête précédente s'exprime plus simplement : Exemple 35
La syntaxe d'une telle expression utilisant un ROW VALUE CONSTRUCTOR est : ( <constructeur de lignes valuées> ) <comparateur> ( <constructeur de lignes valuées> ) Le constructeur de lignes valuées pouvant
être : une liste de colonnes, une liste de valeurs, une liste combinant
colonnes et valeurs ou encore une sous requête :
etc... L'équivalent entre cette construction et celle n'utilisant pas le ROW VALUE CONSTRUCTOR, peut être développée comme suit. Supposons que le premier constructeur de lignes valuées comporte des colonnes de tables de 1 à n et que le second constructeur de ligne valuées comporte des valeurs de 1 à n, c'est à dire : (colonne1, colonne2, ... colonneN) <comparateur> (valeur1, valeur2, ... valeurN) alors cette comparaison est équivalente à :
Toujours basé sur notre jeu d'essais, voici un exemple plus complet :: cherchons tous les événements survenus après 3h12'30" : Exemple 36
Exemple 37 : et sa construction logiquement équivalente :
En fait le ROW VALUE CONSTRUCTOR agit, dans les recherches, un peu comme si l'on visualisait les données de manière fractale Le plus grossier est traité, puis on s'interrese à quelques données plus fine une fois le grossier fixé, et ainsi de suite en fonction du niveau fractal que l'on s'est fixé. NOTA : l'utilisation du ROW VALUE
CONSTRUCTOR avec un critère de comparaison d'égalité donne parfois des
résultats surprenants, qui peuvent défier la logique. Il faut se méfier
d'un recours systématique à une telle construction. Exemple 38 : quels sont les événement survenus à 3h 12 (en utilisant le ROW VALUE CONSTRUCTOR)
Ce qui offre peut d'intérêt il faut bien le dire ! La construction logique équivalente étant : Exemple 39
ENFIN, notez que le ROW VALUE CONSTRUCTOR
possède un intérêt immense, celui de permettre l'insertion multiple
(plusieurs lignes de données) au sein du même ordre INSERT ! Exemple 40 : insertion multiple avec le ROW VALUE CONSTRUCTOR
ATTENTION : seul ORACLE et quelques SGBDR
plus expérimentaux que professionnels (OCELOT par exemple) utilisent une
telle technique ! 9. RésuméVoici les différences entre les moteurs des bases de données :
10. ConclusionCurieusement Paradox n’a pas implémenté les
opérateurs de récupération des valeurs temporelles courantes alors
qu’ils existent en QBE ! Il est facile de s’en passer en passant la date
ou l’heure courante en paramètre de la requête, mais tout de même... En ce qui concerne MS Access, on ne peut
qu’être frappé par le fait que la plupart des fonctions de base des
requêtes sont incompatible avec la norme. Par exemple le LIKE utilise
des jokers différent : * remplace le % et ? remplace le _.
Cela oblige à utiliser une syntaxe propriétaire qui rend la
portabilité des requêtes très difficile d’un SGBDR à l’autre. Mais ne
serait-ce pas là une tactique voulue ??? Autre inconvénient il ne sait
pas traiter le NOT BETWEEN !!! Plus curieux la plupart des SGBDR n'accepte pas l'opérateur de concaténation ||! Dans Sybase comme SQL Server la fonction
modulo s'exprime sous la forme d'un caractère '%' d'ou d'énormes
possibilité de confusions entre les caractères joker du like, comme le
calcul de pourcentage... A quand une release sur ce sujet ??? Le SGBDR le plus proche de la norme est
celui de Sybase, suivi de SQL Server. Le plus complet par son jeu de
fonction est sans doute Oracle.
|