Dans le prcdent article nous avons vu lhistorique de SQL et ses diffrentes composantes. Nous entrons maintenant dans le vif du sujet, en nous intressant au simple SELECT. Simple ? Pas si sr... Dans le dernier document normatif de lISO, la syntaxe de la commande SELECT, est dcrite en plus de 300 pages Cest pourquoi nous nous permettons de mettre en doute la simplicit de la commande SELECT !
1) La commande SELECT
Le SELECT est la commande de base du SQL destine extraire des donnes dune base ou calculer de nouvelles donnes partir dexistantes Voici la syntaxe gnrale d'une commande SELECT :
SELECT [DISTINCT ou ALL] * ou liste de colonnes FROM nom de table ou de la vue [WHERE prdicats] [GROUP BY ordre des groupes] [HAVING condition] [ORDER BY ] liste de colonnes
NOTA : dans cette syntaxe, les mots clef du SQL sont en majuscule droite, les paramtres en minuscule italique 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 :
SELECT Spcification des colonnes du rsultat FROM Spcification des tables sur lesquelles porte l'ordre WHERE Filtre portant sur les donnes (conditions remplir pour que les lignes soient prsentes dans le rsultat) GROUP BY Dfinition d'un groupe (sous ensemble) HAVING Filtre portant sur les rsultats (conditions de regroupement des lignes) ORDER BY Tri des donnes du rsultat
NOTA : La plupart du temps, la difficult rside dans la comprhension de la diffrence entre le filtre WHERE et le filtre HAVING. Disons plus pragmatiquement que le filtre WHERE permet de filtrer les donnes des tables tandis que le filtre HAVING permet de filtrer les donnes du rsultat.
REMARQUE : pour spcifier une valeur littrale il faut l'entourer de guillemets simples.
Un premier exemple basique : exemple 1 SELECT CLI_NOM, CLI_PRENOM FROM T_CLIENT WHERE TIT_CODE = M. CLI_NOM CLI_PRENOM ------- ---------- DUPONT Alain MARTIN Marc BOUVIER Alain DUBOIS Paul DREYFUS Jean FAURE Alain PAUL Marcel DUVAL Arsne PHILIPPE Andr CHABAUD Daniel BAILLY Jean-Franois ... Permet de trouver les noms et prnoms des clients dont le titre est M. (monsieur). NOTA : comme tous les paramtres prendre sous forme de littraux doivent tre exprimes entours d'apostrophes (simple ctes), il faut ddoubler un tel caractres s'il s'avre prsent dans la chane utilis.
1.1) l'oprateur * (toile)
Le caractre * (toile) rcupre toutes les colonnes de la table prcise dans la clause FROM de la requte. Juste aprs le mot clef SELECT, on prcise les colonnes de la table qui doivent tre prsentes dans la rponse. Lutilisation du caractre toile ramne toutes les colonnes de la table dans la rponse. Dans le cas contraire il faut expressment nommer chacune des colonnes et les sparer par des virgules.
exemple 2 SELECT * FROM T_CLIENT WHERE TIT_CODE = 'M.' CLI_ID TIT_CODE CLI_NOM CLI_PRENOM CLI_ENSEIGNE ------- -------- -------- ---------- ------------ 1 M. DUPONT Alain NULL 2 M. MARTIN Marc Transports MARTIN & fils 3 M. BOUVIER Alain NULL 4 M. DUBOIS Paul NULL 5 M. DREYFUS Jean NULL 6 M. FAURE Alain Boulangerie du march 11 M. PAUL Marcel Cie Internationale des Machines Electromcaniques 12 M. DUVAL Arsne NULL 13 M. PHILIPPE Andr NULL 16 M. CHABAUD Daniel NULL ... Notons tout de suite la prsence plusieurs reprises du mot clef "NULL" dans la colonne CLI_ENSEIGNE. Non il ne s'agit pas d'une enseigne particulire, mais simplement de l'absence d'information. Nous verrons que l'absence d'information, c'est le marquer "NULL" qui diffre de la chane de caractre vierge ("") ou encore du zro.
1.2) l'oprateur DISTINCT (ou ALL)
Lorsque le moteur construit la rponse, il rapatrie toutes les lignes correspondantes, gnralement dans lordre ou il les trouve, mme si ces dernires sont en double, c'est dire qu'il rcupre toutes les lignes (ALL par dfaut). Cest pourquoi il est souvent ncessaire dutiliser le mot clef DISTINCT qui permet dliminer les doublons dans la rponse
exemple 3 SELECT CLI_PRENOM FROM T_CLIENT WHERE TIT_CODE = 'M.' CLI_PRENOM ---------- Alain Marc Alain Paul Jean Alain Marcel Arsne Andr Daniel ... SELECT distinct CLI_PRENOM FROM T_CLIENT WHERE TIT_CODE = 'M.' CLI_PRENOM ---------- Alain Alexandre Andr Arnaud Arsne Bernard Christian Christophe Daniel Denis ...
1.3) Oprateur AS
Vous pouvez rajouter autant de colonnes que vous le dsirez en utilisant le mot clef AS. En principe loprateur AS sert donner un nom de nouvelles colonnes cres par la requte. exemple 5 SELECT CLI_NOM as NOM, 'homme' as SEXE FROM T_CLIENT WHERE TIT_CODE = 'M.' NOM SEXE ------- ----- DUPONT homme MARTIN homme BOUVIER homme DUBOIS homme DREYFUS homme FAURE homme PAUL homme DUVAL homme PHILIPPE homme CHABAUD homme ...
1.4) Oprateur de concatnation
L'oprateur || (double barre verticale) permet de concatner des champs de type caractres exemple 6 SELECT TIT_CODE || ' ' || CLI_PRENOM || ' ' || CLI_NOM as NOM FROM T_CLIENT NOM ----------------------- M. Alain DUPONT M. Marc MARTIN M. Alain BOUVIER M. Paul DUBOIS M. Jean DREYFUS M. Alain FAURE M. Paul LACOMBE Melle. Evelyne DUHAMEL Mme. Martine BOYER M. Martin MARTIN ... Nanmoins on trouve dans certains SGBDR le + comme oprateur de concatnation, comme la fonction CONCAT.
1.5) Oprateur mathmatiques de base
On, peut utiliser les oprateurs mathmatiques de base pour combiner diffrentes colonnes (,+,-, *, /,). exemple 7 SELECT CHB_ID, TRF_CHB_PRIX * 1.206 AS TARIF_TTC FROM TJ_TRF_CHB WHERE TRF_DATE_DEBUT = '2001-01-01' CHB_ID TARIF_TTC ------ --------- 1 424,51 2 482,40 3 617,47 4 424,51 5 463,10 6 482,40 7 424,51 8 540,29 9 482,40 10 617,47 ...
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 :
FROM nom_de_table ou nom_de_la_vue surnom
Nous verrons dans quel cas ce renom est ncessaire ou obligatoire. NOTA : certains auteurs prfre utiliser le mot d'alias que nous rejetons car il indique souvent un autre concept, ou de synonyme, que nous acceptons de manire timore...
1.7) Utilisation du caractre double quote (guillemet)
Lorsquun nom dun lment dune base de donnes (table, colonne par exemple) est identique un mot clef du SQL, il convient de lentourer de guillemets (double quote). En principe, les mots rservs du SQL sont dconseill pour nommer des objets du modle physique de donnes... Imaginons une table de nom JOIN, compose des champs suivants : NOM SELECT DATE NOT ------- ------ ------- --- DURAND Oui 1999-11-12 F DUVAL Non 1998-01-17 M Exemple 8 : nous dsirons slectionner les colonnes SELECT et DATE lorsque la colonne NOT vaut F... SELECT SELECT, DATE FROM JOIN WHERE NOT = 'F' ERREUR ! SELECT "SELECT", "DATE" FROM "JOIN" WHERE "NOT" = 'F' Correct : on entoure les mots clefs du SQL par des doubles ctes Cela est aussi ncessaire lorsque le nom (d'une colonne ou d'une table) est compos de caractres particuliers tels que les blancs ou autres, ce qui est a viter. REMARQUE : les noms des identifiants d'objet de base de donnes doivent tre crit dans le jeux de caractres restreint suivant : [A..Z] + [a..z] + [0..9] + [ _ ]. Ils ne doivent pas commencer par un chiffre et sont insensible la casse (indiffrence entre majuscule et minuscule).
2) Clause ORDER BY
ORDER BY colonne1 | 1 [ASC ou DESC ] [, colonne2 | 2 [ASC ou DESC ] ...
Cette clause permet de dfinir le tri des colonnes de la rponse, soit en prcisant le nom littral de la colonne, soit en prcisant son n d'ordre dans l'numration qui suit le mot clef SELECT. ASC spcifie lordre ascendant et DESC lordre descendant du tri. ASC ou DESC peut tre omis, dans ce cas c'est l'ordre ascendant qui est utilis par dfaut. Bien que la clause ORDER BY ne soit pas ncessaire, il est souvent utile de trier la rponse en fonction des colonnes. En revanche le temps de rponse s'en ressent souvent. Pour spcifier l'ordre de tri, on doit placer les noms des colonnes spares par des virgules juste aprs le mot clef "ORDER BY", dans l'ordre voulu.. On peut aussi utiliser le rang de chaque colonne dans l'ordre spcifi dans la clause SELECT. Attention : le tri est un tri interne, il ne faut donc placer dans cette clause que les noms des colonnes prsentes dans la clause SELECT. Souvent, le fait de placer DISTINCT suffit, en gnral, tablir un tri puisque le moteur doit se livrer une comparaison des lignes mais ce mcanisme n'est pas garantit car ce tri seffectue dans un ordre non contrlable qui peut varier dun serveur lautre. exemple 9 SELECT CLI_NOM, CLI_PRENOM FROM T_CLIENT ORDER BY CLI_NOM, CLI_PRENOM ou SELECT CLI_NOM, CLI_PRENOM FROM T_CLIENT ORDER BY 1, 2 CLI_NOM CLI_PRENOM -------- ---------- AIACH Alexandre ALBERT Christian AUZENAT Michel BACQUE Michel BAILLY Jean-Franois BAVEREL Frdric BEAUNEE Pierre BENATTAR Bernard BENATTAR Pierre BENZAQUI Jol ... REMARQUE : les marqueur NULL sont situes en premier dans l'ordre ainsi tablit. NOTA : Un problme, qui nest pas rsolu, est de pouvoir choisir lordre des colonnes de la rponse. Sur certains serveurs cela peut tre obtenu en plaant les noms des colonnes obtenir dans lordre o lon veut les voir apparatre dans la clause SELECT, mais cette possibilit n'est jamais garantie... ATTENTION : la clause ORDER BY est la dernire clause de tout ordre SQL et ne doit figurer qu'une seule fois dans le SELECT, mme s'i l existe des requtes imbriques ou un jeu de requtes ensemblistes
3) La clause WHERE
WHERE prdicats
Le prdicat doit contenir nimporte quelle expression logique renvoyant une valeur vrai. Ainsi, une requte aussi stupide que la suivante, est suppose fonctionner : exemple 10 SELECT CLI_NOM FROM T_CLIENT WHERE 1=1 CLI_NOM ------- DUPONT MARTIN BOUVIER DUBOIS DREYFUS FAURE LACOMBE DUHAMEL BOYER MARTIN Attention : la plupart des SGBDR ne comportent pas de colonne de type boolen. Une requte comme la premire risque d'chouer. exemple 1.12 SELECT * FROM TJ_CHB_PLN_CLI WHERE CHB_PLN_CLI_OCCUPE ERREUR ! bien que CHB_PLN_CLI_OCCUPE puisse tre du boolen, la plupart des compilateur SQL n'accepte pas ce test direct. SELECT * FROM TJ_CHB_PLN_CLI WHERE CHB_PLN_CLI_OCCUPE = True CORRECT ... Mais sur certains compilateur SQL il faut faire : CHB_PLN_CLI_OCCUPE = 'True' (littral). Si le type boolen n'existe pas, alors il faut faire CHB_PLN_CLI_OCCUPE = 1 si l'on a choisi de dfinir les boolens comme INTEGER(1) avec 0 et 1 exemple 11
3.1) Oprateurs de comparaison
Dans la clause WHERE, vous disposez de diffrents oprateurs de comparaisons logiques :
WHERE valeur1 [NOT et] = ou < ou <= ou > ou >= ou <>valeur2 [OR ou AND ...]
exemple 12 SELECT CLI_NOM, CLI_PRENOM FROM T_CLIENT WHERE CLI_NOM >= 'A' AND CLI_NOM <'E' ou SELECT CLI_NOM, CLI_PRENOM FROM T_CLIENT WHERE (CLI_NOM >= 'A') AND (CLI_NOM <'E') plus lisible ! CLI_NOM CLI_PRENOM ------- ---------- DUPONT Alain BOUVIER Alain DUBOIS Paul DREYFUS Jean DUHAMEL Evelyne BOYER Martine DUVAL Arsne DAUMIER Amlie CHABAUD Daniel BAILLY Jean-Franois ...
Ici on obtient tous les noms et prnoms des clients dont le nom commence par les lettres A, B, C ou D. Attention : dans certains moteurs de requte SQL loprateur diffrend de (<>) scrit !=
3.2) Oprateur IN
L'oprateur IN permet de rechercher si une valeur se trouve dans un ensemble donn, quel que soit le type des valeurs de rfrence spcifies (alpha, numrique, date). Bien entendu, il est possible dinverser le fonctionnement de loprateur IN en lui adjoignant loprateur NOT.
exemple 13 SELECT TIT_CODE, CLI_NOM, CLI_PRENOM FROM T_CLIENT WHERE TIT_CODE IN ('Mme.', 'Melle.') TIT_CODE CLI_NOM CLI_PRENOM -------- ---------- ------- --- Mme. BOYER Martine Mme. GALLACIER Nolle Mme. HESS Lucette Mme. LETERRIER Monique Mme. MARTINET Carmen Mme. DAVID Jacqueline Mme. MOURGUES Jacqueline Mme. ZAMPIERO Annick Mme. ROURE Marie- Louise Mme. DE CONINCK Patricia ...
On recherche les clients de sexe fminin, bass sur le code titre Le contenu de la parenthse peut tre remplac par le resultat d'une requte possdant une colonne unique. Dans ce cas on parle de requtes imbriques, ce que nous verrons plus loin.
3.3) Oprateur BETWEEN
L'oprateur BETWEEN permet de rechercher si une valeur se trouve dans un intervalle donn, quel que soit le type des valeurs de rfrence spcifies (alpha, numrique, date) Ainsi, la requte vue dans l'exemple 12 peut s'crire :
Exemple 14 SELECT CLI_NOM, CLI_PRENOM FROM T_CLIENT WHERE CLI_NOM BETWEEN 'A' AND 'E' CLI_NOM CLI_PRENOM ------- ---------- DUPONT Alain BOUVIER Alain DUBOIS Paul DREYFUS Jean DUHAMEL Evelyne BOYER Martine DUVAL Arsne DAUMIER Amlie CHABAUD Daniel BAILLY Jean-Franois ...
NOTA : les oprateurs IN et BETWEEN sont trs pratiques dans le cas o lon dsire effectuer des requtes o lutilisateur peut saisir une liste de choix multiples (IN) ou une plage de valeur (BETWEEN).
3.4) Oprateurs LIKE
L'oprateur LIKE permet deffectuer une comparaison partielle. Il est surtout employ avec les colonnes contenant des donnes de type alpha. Il utilise les jokers % et _ (pour cent et blanc soulign). Le joker % remplace n'importe quelle chane de caractres, y compris la chane vide. Le blanc soulign remplace un et un seul caractre.
exemple 15 SELECT CLI_NOM, CLI_PRENOM FROM T_CLIENT WHERE CLI_NOM LIKE B% CLI_NOM CLI_PRENOM ------- ---------- BOUVIER Alain BOYER Martine BAILLY Jean-Franois BOUCHET Michel BEAUNEE Pierre BERGER Jean-Pierre BOURA Andr BENZAQUI Jol BAVEREL Frdric BERTRAND Christophe ...
On recherche les client dont le nom commence par B. Mais si vos donnes sont susceptibles de contenir un des deux caractres joker, alors il faut recourir une squence dchappement, laide du mot clef ESCAPE Cherchons les clients dont l'enseigne contient au moins un caractre blanc soulign :
exemple 16 SELECT * FROM T_CLIENT WHERE CLI_ENSEIGNE LIKE %_% CLI_ID TIT_CODE CLI_NOM CLI_PRENOM CLI_ENSEIGNE ------ -------- ---------- ------------- --------------- 2 M. MARTIN Marc Transports MARTIN & fils 6 M. FAURE Alain Boulangerie du march 10 M. MARTIN Martin HERMAREX IMPORT_EXPORT 11 M. PAUL Marcel Cie Internationale des Machines Electrom... 17 M. BAILLY Jean-Franois Entreprise DUPONT CHAUFFAGE 24 M. CHTCHEPINE Dominique HOTEL *** DE LA GARE 26 M. GARREAU Paul IBM Corp. 34 Mme. GALLACIER Nolle Transports GALLACIER 42 Mme. LETERRIER Monique SA AROMAX ENTREVONT 49 M. COULOMB Renaud Cabinet COULOMN et CALEMANT ... SELECT * FROM T_CLIENT WHERE CLI_ENSEIGNE LIKE '%#_%' ESCAPE '#' CLI_ID TIT_CODE CLI_NOM CLI_PRENOM CLI_ENSEIGNE ------ -------- ---------- ------------- ------------- 10 M. MARTIN Martin HERMAREX IMPORT_EXPORT
Pour traiter ce cas, on dfini # comme caractre dchappement. Le caractre qui suit ce caractre dchappement est donc interprt comme un caractre et non comme un joker. NOTA : loprateur LIKE effectue une recherche en tenant compte de la diffrence entre lettres majuscules et minuscules. Si vous voulez effectuer une recherche en ne tenant aucunement compte de la diffrence entre majuscules et minuscules, il convient dutiliser les oprateurs LOWER et UPPER (voir ci dessous). Mais la plupart du temps, l'utilisation du like dans un SGBDR donn ignore la casse.
3.5) Rsum des oprateurs pour les prdicats de la clause WHERE
Voici une tableau rsumant les principaux oprateurs utiliss pour la construction des prdicats :
oprateurs de comparaisons = <> < <= > >= connecteurs logiques {OR | AND} oprateur de ngation NOT parenthses ( ... ) oprateurs mathmatiques + - * / comparaison logique IS [NOT] {TRUE | FALSE | UNKNOWN} comparaison avec valeur IS [NOT] NULL intervalle valeur BETWEEN borne_basse AND borne_haute comparaison partielle de chane de caractres valeur LIKE motif [ESCAPE echappement] comparaison une liste de valeur valeur [NOT] IN (liste)
4) Fonctions diverses
4.1) Transtypage l'aide de la fonction CAST
Il permet de changer le type de donnes d'une colonne afin deffectuer une comparaison de donnes de type htrogne par exemple entre un champ contenant des donnes numriques et un champ contenant des donnes de type chane de caractres Sa syntaxe est CAST(colonne AS nouveau type).
Loprateur CAST permet de transtyper les valeurs contenues dans une colonne. Bien entendu il faut qu'un type de donne puisse tre convertis dans un autre type (compatibilit de types) afin que le rponse ne soit pas entch d'erreurs ou d'ommissions.
exemple 18 SELECT ADR_VILLE, CAST(ADR_CP AS INTEGER) + 1 FROM T_ADRESSE ADR_VILLE ADR_CP ADR_CP + 1 ------------ ------ ---------- VERSAILLES 78000 78001 MONTMAIZIN 11254 11255 PARIS 75015 75016 VERGNOLLES CEDEX 452 84524 84525 MARSEILLE 13002 13003 PARIS 75012 75013 BONNEUIL CEDEX 94152 94153 PARIS 75012 75013 PARIS 75014 75015 PARIS 75017 75018 ...
4.2) Mise en majuscule / Minuscule
Les oprateurs LOWER et UPPER permettent de mettre en majuscule ou en minuscule des chanes de caractres dans les requtes.
exemple 19 SELECT upper(CLI_PRENOM), lower(CLI_NOM) FROM T_CLIENT CLI_NOM CLI_PRENOM ------- ---------- ALAIN dupont MARC martin ALAIN bouvier PAUL dubois JEAN dreyfus ALAIN faure PAUL lacombe EVELYNE duhamel MARTINE boyer MARTIN martin ... NOTA : pour effectuer une recherche en ne tenant aucunement compte de la diffrence entre majuscules et minuscules, il faut utiliser loprateur UPPER (ou lower mais attention la transformation des accents !) :
4.3) Supprimer les blancs (ou tout autre caractres)
La fonction TRIM permet de supprimer en tte ou en queue (ou les deux) le blanc ou tout autre caractre spcifi.
TRIM ([LEADING ou TRAILING ou BOTH] [caractre] FROM nom de colonne) LEADING : suppression en tte TRAILING : suppression en queue BOTH : suppression en tte et en queue
Dans notre table tlphone, nous voulons supprimer le zro de tte des n afin de pouvoir les communiquer aux trangers qui nont pas besoin de composer ce chiffre (ils doivent simplement composer le 00 33 suivi du numro 9 chiffres).
exemple 21 SELECT TEL_NUMERO, 00~33 || TRIM(LEADING 0 FROM TEL_NUMERO) AS TEL_INTERNATIONAL FROM T_TELEPHONE TEL_NUMERO TEL_INTERNATIONAL -------------- ----------------- 01-45-42-56-63 00~33 1-45-42-56-63 01-44-28-52-52 00~33 1-44-28-52-52 01-44-28-52-50 00~33 1-44-28-52-50 06-11-86-78-89 00~33 6-11-86-78-89 02-41-58-89-52 00~33 2-41-58-89-52 01-51-58-52-50 00~33 1-51-58-52-50 01-54-11-43-21 00~33 1-54-11-43-21 06-55-41-42-95 00~33 6-55-41-42-95 01-48-98-92-21 00~33 1-48-98-92-21 01-44-22-56-21 00~33 1-44-22-56-21 ... NOTA : certains serveurs SQL proposent diffrentes fonctions comme LTRIM et RTRIM pour une suppression des blancs en tte ou en queue.
4.4) Extraire une sous chane
La fonction SUBSTRING permet dextraire une sous chane dune chane de caractre. Elle a besoin de lordre du premier caractre et du nombre de caractres sur lequel elle doit oprer.
SUBSTRING ( nom de colonne FROMnTOm) Extrait la sous chane de nom de colonne en commenant n sur m caractres.
exemple 22
SELECT CLI_NOM, CLI_PRENOM, SUBSTRING(CLI_PRENOM FROM 1 FOR 1) || SUBSTRING(CLI_NOM FROM 1 FOR 1) AS INITIALES FROM T_CLIENT CLI_NOM CLI_PRENOM INITIALES ------- ---------- --------- DUPONT Alain AD MARTIN Marc MM BOUVIER Alain AB DUBOIS Paul PD DREYFUS Jean JD FAURE Alain AF LACOMBE Paul PL DUHAMEL Evelyne ED 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) Oprateur de traitement des dates
4.5.1) Extraire un paramtre temporel d'une date
Loprateur EXTRACT permet dextraire depuis une date, le jour le mois ou lanne
EXTRACT ( YEAR ou MONTH ou DAY FROM nom de colonne )
Dans la table des rservation on recherche l'identifiant des chambres ayant t rserves au cours du mois de mai de n'importe quelle anne et pour 3 personnes
exemple 23
SELECT distinct CHB_ID FROM TJ_CHB_PLN_CLI WHERE EXTRACT(MONTH FROM PLN_JOUR) = 5 AND CHB_PLN_CLI_RESERVE = 1 AND CHB_PLN_CLI_NB_PERS = 3 CHB_ID ------ 1 5 6 8 11 12 16 17 18 20 NOTA : il est dommage de constater que la fonction EXTRACT du standard SQL, souvent fort utile, est rarement prsente dans les moteurs de bases de donnes. Ni Access, ni Oracle, ni Sybase, ni SQL Server en sont dot. 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.
4.5.2) Heure et date courante
Lheure courante, la date courante et le combin date/heure courant peuvent tre obtenu laide des fonctions CURRENT_DATE, CURRENT_TIME et CURRENT_TIMESTAMP exemple 24
SELECT distinct CHB_ID FROM TJ_CHB_PLN_CLI WHERE (CHB_PLN_CLI_RESERVE = 1) AND PLN_JOUR BETWEEN CURRENT_DATE and CHB_ID ------ 1 5 6 CURRENT_DATE + 14 AND CHB_PLN_CLI_NB_PERS = 3 attention, le rsultat de cette requte varie en fonction de la date laquelle vous l'excutez ! 8 11 12 16 17 18 20
Cette requte renvoi les chambres rserves 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 normalise des fonctions de recherche de temps courant. Voici les fonctions spcifiques aux diffrents serveurs SQL :
Il est possible de raliser des comptages statistiques sur les colonnes, l'aide des oprateurs AVG (moyenne), MAX (maximum), MIN (minimum), SUM (total), COUNT (nombre). On les appellent aussi fonctions d'agrgations.
exemple 25
SELECT AVG(TRF_CHB_PRIX) as MOYENNE, MAX(TRF_CHB_PRIX) as MAXI, MIN(TRF_CHB_PRIX) as MINI, SUM(TRF_CHB_PRIX) as TOTAL, COUNT(TRF_CHB_PRIX) as NOMBRE FROM TJ_TRF_CHB WHERE TRF_DATE_DEBUT = 2001-01-01 MOYENNE MAXI MINI TOTAL NOMBRE -------- -------- -------- ---------- ------ 406,74 F 512,00 F 352,00 F 7 728,00 F 19
Cette requte calcule la moyenne, le montant maximum, minimum, la totalisation et le nombre des tarifs de chambre pour la date de dbut du premier janvier 2001.
4.7) Autres fonctions normalises
BIT_LENGTH Taille d'une colonne de type BIT ou BIT VARYING (nombre de bits) CHAR_LENGTH Taille d'une colonne de type caractre (nombre de caractres) OCTET_LENGTH Taille d'une colonne de type caractre (nombre d'octets) CURRENT_DATE Date en cours CURRENT_TIME Heure en cours CURRENT_TIMESTAMP Date et heure en cours CONVERT Conversion paramtre d'une chane de caractres POSITION Position d'une chane de caractres dans une sous chane TRANSLATE Traduction d'une chane de caractres dans un format spcifi
4.8) Autres oprateurs mathmatiques (non normaliss)
Les oprateurs ci dessous peuvent tre implments dans diffrents moteurs.
ABS valeur absolue MOD modulo SIGN signe SQRT racine carre CEIL plus petit entier FLOOR plus grand entier ROUND arrondi TRUNC tronqu EXP exponentielle LN logarithme nprien LOG logarithme dcimal POWER puissance COS cosinus COSH cosinus hyperbolique SIN sinus SINH sinus hyperbolique TAN tangente TANH tangente hyperbolique PI constante Pi
Certains sont rarement implments du fait que les SGBDR sont axs sur linformatique de gestion, la collecte et le traitement dinformations et non le calcul mathmatique.
6) Ngation de valeurs
C'est l'oprateur NOT qui ralise la ngation de valeurs et inverse la valeur logique d'un prdicat. L'oprateur NOT peut tre combin avec la plupart des oprateurs de comparaison. Mais il devient trs intressant lorsqu'il est combin aux oprateurs IN, BETWEEN, LIKE et NULL Recherchons par exemples 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 particulirement superstitieux...
exemple 29
SELECT CHB_ID, CHB_NUMERO, CHB_COUCHAGE FROM T_CHAMBRE WHERE NOT (CAST(CHB_NUMERO AS VARCHAR(10)) LIKE '%4%') AND CHB_NUMERO NOT IN ('7', '13') AND CHB_COUCHAGE >= 3 CHB_ID CHB_NUMERO CHB_COUCHAGE ----------- ---------- ------------
Nous verrons que le NOT IN est particulirement prcieux dans les requtes imbriques, c'est dire les requtes multi- tables. Nous voulons maintenant le nom des clients qui ne commence pas par 'DU' :
exemple 1.30 SELECT CLI_NOM FROM T_CLIENT WHERE CLI_NOM NOT LIKE 'DU%' CLI_NOM -------------------------------- MARTIN BOUVIER DREYFUS Remarque
En ce qui concerne MS Access, on ne peut qutre frapp par le fait que la plupart des fonctions de base des requtes sont incompatible avec la norme. Par exemple le LIKE utilise des jokers diffrent : * remplace le % et ? remplace le _. Cela oblige utiliser une syntaxe propritaire qui rend la portabilit des requtes trs difficile dun SGBDR lautre. Mais ne serait-ce pas l une tactique voulue ??? Autre inconvnient il ne sait pas traiter le NOT BETWEEN !!! Plus curieux la plupart des SGBDR n'accepte pas l'oprateur de concatnation ||!
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.
1Z C1 CW m m Z @WUW @m2UW " UW CUI2W 1m2 12WCW2UC ZLmZL
Ug 1W wCUI2W C CCUUWI 2mU2W CW 2W@WW 2 @UUW2 mUW
Les jointures permettent d'exploiter pleinement le modle relationnel des tables d'une base de donnes. Elle sont faites pour mettre en relation deux (ou plus) tables concourant rechercher la rponse des interrogations. Une jointure permet donc de combiner les colonnes de plusieurs tables. Il existe en fait diffrentes natures de jointures que nous expliciterons plus en dtail. Retenez cependant que la plupart des jointures entre tables s'effectuent en imposant l'galit des valeurs d'une colonne d'une table une colonne d'une autre table. On parle alors de jointure naturelle ou qui- jointure. Mais on trouve aussi des jointures d'une table sur elle mme. On parle alors d'auto-jointure. Enfin il arrive que l'on doive procder des jointures externe, c'est dire joindre une table une autre, mme si la valeur de liaison est absente dans une table ou l'autre. Enfin, dans quelques cas, on peut procder des jointures htrognes, c'est dire que l'on remplace le critre d'galit par un critre d'ingalit ou de diffrence. Nous verrons au moins un cas de cet espce. Une jointure entre tables peut tre mise en oeuvre, soit l'aide des lments de syntaxe SQL que nous avons dj vu, soit l'aide d'une clause spcifique du SQL, la clause wLUW. Nous allons commencer par voir comment l'aide du SQL de base nous pouvons exprimer une jointure. UU 12WUUW2 WmU CW CUI2W Rappel de la syntaxe du SELECT : CZ1ZL [LUCUWL ou m11] ou liste de colonnes 1ZLD nom des tables ou des vues C'est ici le pluriel du la partie FROM qui change tout... Tchons donc de rcuprer les n des tlphones associs aux clients exemple 1 SELECT CLI_NOM, TEL_NUMERO FROM T_CLIENT, T_TELEPHONE CLI_NOM TEL_NUMERO ------- -------------- DUPONT 01-45-42-56-63 DUPONT 01-44-28-52-52 DUPONT 01-44-28-52-50 DUPONT 06-11-86-78-89 DUPONT 02-41-58-89-52 DUPONT 01-51-58-52-50 DUPONT 01-54-11-43-21 DUPONT 06-55-41-42-95 DUPONT 01-48-98-92-21 DUPONT 01-44-22-56-21 ... Cette requte ne possde pas de critre de jointure entre une table et l'autre. Dans ce cas, le compilateur SQL calcule le produit cartsien des deux ensembles, c'est dire qu' chaque ligne de la premire table, il accole l'ensemble des lignes de la seconde la manire d'une "multiplication des petits pains" ! Nous verrons qu'il existe une autre manire, normalise cette fois, de gnrer ce produit cartsien. Mais cette requte est proscrire. Dans notre exemple elle gnre 17 400 lignes... ,OIDXWGRQFGpILQLUDEVROXPHQWXQFULWqUHGHMRLQWXUH Dans le cas prsent, ce critre est la correspondance entre les colonnes contenant la rfrence de l'identifiant du client (CLI_ID). exemple 2 SELECT CLI_NOM, TEL_NUMERO FROM T_CLIENT, T_TELEPHONE WHERE CLI_ID = CLI_ID CLI_NOM TEL_NUMERO ------- -------------- DUPONT 01-45-42-56-63 DUPONT 01-44-28-52-52 DUPONT 01-44-28-52-50 DUPONT 06-11-86-78-89 DUPONT 02-41-58-89-52 DUPONT 01-51-58-52-50 DUPONT 01-54-11-43-21 DUPONT 06-55-41-42-95 Nous n'avons pas fait mieux, car nous avons cr une clause toujours vrai, un peu la manire de 1 = 1 ! En fait il nous manque une prcision : il s'agit de dtermin de quelles table proviennent les colonnes CLI_ID de droite et de gauche. Cela ce prcise l'aide d'une notation pointe en donnant le nom de la table. Il est donc ncessaire d'indiquer au compilateur la provenance de chacune des colonnes CLI_ID et donc d'oprer une distinction entre l'une et l'autre colonne. Ainsi, chaque colonne devra tre prcde du nom de la table, suivi d'un point. exemple 3 SELECT CLI_NOM, TEL_NUMERO FROM T_CLIENT, T_TELEPHONE WHERE T_CLIENT.CLI_ID = T_TELEPHONE.CLI_ID CLI_NOM TEL_NUMERO ------- -------------- DUPONT 01-45-42-56-63 DUPONT 01-44-28-52-52 DUPONT 01-44-28-52-50 BOUVIER 06-11-86-78-89 DUBOIS 02-41-58-89-52 DREYFUS 01-51-58-52-50 DUHAMEL 01-54-11-43-21 BOYER 06-55-41-42-95 MARTIN 01-48-98-92-21 MARTIN 01-44-22-56-21 ... On tombe ici 174 enregistrements dans la table !!! Mais il existe une autre faons de faire, plus simple encore. On utilise la technique du "2ICUUmW", c'est dire que l'on attribut un surnom chacune des tables prsente dans la partie FROM du SELECT : exemple 4 SELECT CLI_NOM, TEL_NUMERO FROM T_CLIENT C, T_TELEPHONE T WHERE C.CLI_ID = T.CLI_ID CLI_NOM TEL_NUMERO ------- -------------- DUPONT 01-45-42-56-63 DUPONT 01-44-28-52-52 DUPONT 01-44-28-52-50 BOUVIER 06-11-86-78-89 DUBOIS 02-41-58-89-52 DREYFUS 01-51-58-52-50 DUHAMEL 01-54-11-43-21 BOYER 06-55-41-42-95 MARTIN 01-48-98-92-21 MARTIN 01-44-22-56-21 ... Ici, la table T_CLIENT a t surnomme "C" et la table T_TELEPHONE "T". Bien entendu, et comme dans les requtes monotabulaires ont peut poser des conditions supplmentaires de filtrage dans la clause where. Cherchons par exemple les clients dont les numros de tlphone correspondent un fax : exemple 5 SELECT CLI_NOM, TEL_NUMERO FROM T_CLIENT C, T_TELEPHONE T WHERE C.CLI_ID = T.CLI_ID AND TYP_CODE = 'FAX' CLI_NOM TEL_NUMERO ------- -------------- DUPONT 01-44-28-52-50 MARTIN 01-44-22-56-21 DUHAMEL 01-54-11-43-89 DUPONT 05-59-45-72-42 MARTIN 01-47-66-29-55 DUBOIS 04-66-62-95-64 DREYFUS 04-92-19-18-58 DUHAMEL 01-55-60-93-81 PHILIPPE 01-48-44-86-19 DAUMIER 01-48-28-17-95 ... Le fait de placer comme critre de jointure entre les tables, l'oprateur logique "gal" donne ce que l'on apelle une "W@U" CUI2W". WLm : on peut aussi utiliser les surnoms dans la partie qui suit immdiatement le mot clef SELECT. Ainsi l'exemple 4, peut aussi c'crire : exemple 6 SELECT C.CLI_ID, C.CLI_NOM, T.TEL_NUMERO FROM T_CLIENT C, T_TELEPHONE T WHERE C.CLI_ID = T.CLI_ID AND T.TYP_CODE = FAX CLI_ID CLI_NOM TEL_NUMERO ------ ------- -------------- 1 DUPONT 01-44-28-52-50 10 MARTIN 01-44-22-56-21 8 DUHAMEL 01-54-11-43-89 1 DUPONT 05-59-45-72-42 2 MARTIN 01-47-66-29-55 4 DUBOIS 04-66-62-95-64 5 DREYFUS 04-92-19-18-58 8 DUHAMEL 01-55-60-93-81 13 PHILIPPE 01-48-44-86-19 15 DAUMIER 01-48-28-17-95 ... C'est particulirement pratique lorsque l'on veut rcuprer une colonne qui se retrouve dans les deux tables, ce qui est souvent le cas de la (ou les) colonne de clef trangre qui permet justement d'assurer la jointure. Pour joindre plusieurs tables, on peut utiliser le mme processus de manire rptitive... exemple 7 SELECT C.CLI_ID, C.CLI_NOM, T.TEL_NUMERO, E.EML_ADRESSE, A.ADR_VILLE FROM T_CLIENT C, T_TELEPHONE T, T_ADRESSE A, T_EMAIL E WHERE C.CLI_ID = T.CLI_ID AND C.CLI_ID = A.CLI_ID AND C.CLI_ID = E.CLI_ID CLI_ID CLI_NOM TEL_NUMERO EML_ADRESSE ADR_VILLE ------ -------- -------------- -------------------- --------- 1 DUPONT 01-45-42-56-63 alain.dupont@wanadoo.fr VERSAILLES 1 DUPONT 05-59-45-72-42 alain.dupont@wanadoo.fr VERSAILLES 1 DUPONT 05-59-45-72-24 alain.dupont@wanadoo.fr VERSAILLES 1 DUPONT 01-44-28-52-50 alain.dupont@wanadoo.fr VERSAILLES 1 DUPONT 01-44-28-52-52 alain.dupont@wanadoo.fr VERSAILLES 2 MARTIN 01-47-66-29-55 plongeur@aol.com VERGNOLLES 5 DREYFUS 04-92-19-18-58 pdreyfus@club-internet.fr PARIS DmUC mZWULW De mme que nous l'avons vu dans l'exemple 2.4, ne sont visible ici que les lignes clients ayant A LA FOIS, au moins une adresse, un e mail et au moins un numro de tlphone... Si nous avions voulu une liste complte des clients avec toutes les coordonnes disponibles, nous aurions du faire une requte externe sur les tables... U LU22W2WI @W CW CUI2W _Im2WUUW_ W@U_ ICI W@U_ mC_ W2W2IW_ WW2CWIW_ C2CUWW W IUCIg Lorsque nous tudions le modle relationnel de notre base de donnes exemple nous avons vu que le modle physique des donnes, rpercute les clefs des tables matres en tant que clefs trangres des tables pour lesquelles une jointure est ncessaire. En utilisant la jointure entre clefs primaires et clefs secondaires base sur l'galit des valeurs des colonnes nous excutons ce que les professionnels du SQL appelle une CUI2W Im2WUUW. Il est aussi possible de faire des W@U" CUI2W qui ne sont pas naturelles, soit par accident (une erreur !), soit par ncessit. Il est aussi possible de faire des ICI W@U"CUI2W, c'est dire des jointures base sur un critre diffrent de l'galit, mais aussi des mC" CUI2W, c'est dire de joindre la table sur elle mme. Le cas le plus dlicat comprendre est celui des CUI2W W2W2IW, c'est dire exiger que le rsultat comprenne toutes les lignes des tables (ou d'au moins une des tables de la jointure), mme s'il n'y a pas correspondance des lignes entre les diffrentes tables mise en oeuvre dans la jointure. La CUI2W CIUCI consiste ajouter toutes les donnes des deux tables condition qu'elles soient compatibles dans leurs structures. La CUI2W C2CUWW permet de faire le produit cartsien des tables. Enfin on peut effectuer des 2W@WW WW2CWIW, c'est dire de joindre une table d'une base de donnes, une ou plusieurs autres base de donnes ventuellement mme sur des serveurs diffrents, voire mme sur des serveurs de diffrents types (par exemple joindre une table T_CLIENT de la base BD_COMMANDE d'un serveur Oracle la table T_PROSPECT de la base BD_COMMERCIAL d'un serveur Sybase !).
W LLWCZU1 UD1LZmW Dans la mesure du possible, UUUW CC2 I C@W2mW2 CW CUI2W IC2UmUUW _UC CUW2 wLUWg. En effet : les jointures faites dans la clause WHERE (ancienne syntaxe de 1986 !) ne permettent pas de faire la distinction de prime abord entre ce qui relve du filtrage et ce qui relve de la jointure. Il est priori absurde de vouloir filtrer dans le WHERE (ce qui restreint les donnes du rsultat) et de voiloir "largir" ce rsultat par une jointure dans la mme clause WHERE de filtrage. La lisibilit des requtes est plus grande en utilisant la syntaxe base de JOIN, en isolant ce qui est du filtrage et de la jointure, mais aussi en isolant avec clart chaque condition de jointures entre chaque couples de table L'optimisation d'excution de la requte est souvent plus pointue du fait de l'utilisation du JOIN. Lorsque l'on utilise l'ancienne syntaxe et que l'on supprime la clause WHERE a des fins de tests, le moteur SQL ralise le produit cartsiens des tables ce qui revient la plupart du temps mettre genoux le serveur !
CIm2W IC2UmUUWW CW CUI2W Les jointures normalises s'expriment l'aide du mot clef wLUW dans la clause FROM. Suivant la nature de la jointure, on devra prciser sur quels critres se base la jointure. Voici un tableau rsumant les diffrents types de jointures normalises :
Jointure interne SELECT ... FROM <table gauche> [UWWZZ]wLUW <table droite> LW <condition de jointure> Jointure externe SELECT ... FROM <table gauche> 1Z1 | ZUL | 111 LZZ wLUW <table droite> LW condition de jointure Jointure naturelle SELECT ... FROM <table gauche> WmZm1wLUW <table droite> [CUWL <noms de colonnes>] Jointure croise SELECT ... FROM <table gauche> LZLCCwLUW <table droite> Jointure d'union SELECT ... FROM <table gauche> WULWwLUW <table droite> ZWCm@UUmU2 CW CUI2W IC2UmUUWW U W2UUICUCUW W Im2W CW CUI2W wLUWZZ WmZZ11Z : la jointure seffectue sur les colonnes communes, c'est dire celles de mme nom et type : CZ1ZL colonnes 1ZLD table1 WmZm1wLUW table2 [CUWL col1, col2 ... ] [WZZZ prdicat] ... Le mot clef USING permet de restreindre les colonnes communes prendre en considration wLUWZZ UWZZWZ : la jointure s'effectue entre les tables sur les colonnes prcises dans la condition de jointure : CZ1ZL colonnes 1ZLD table1 t1 [UWWZZ ] wLUW table2 t2 LW FRQGLWLRQ[WZZZ prdicat] ... wLUWZZ ZZZZWZ : la jointure permet de rcuprer les lignes des tables correspondant au critre de jointure, mais aussi celle pour lesquelles il n'existe pas de correspondances. CZ1ZL colonnes 1ZLD table1 t1 [ZUL LZZ | 1Z1 LZZ | 111 LZZ ] wLUW table2 t2 LW FRQGLWLRQ [WZZZ prdicat] ... RIGHT OUTER : la table droite de l'expression clef "RIGHT OUTER" renvoie des lignes sans correspondance avec la table gauche. LEFT OUTER : la table gauche de l'expression clef "LEFT OUTER" renvoie des lignes sans correspondance avec la table droite. FULL OUTER : les deux tables renvoient des lignes sans correspondance entre elles. wLUWZZ LZLUCZZ : la jointure effectue le produit cartsien (la "multiplication") des deux tables. Il n'y a pas de condition CZ1ZL colonnes 1ZLD table1 t1 LZLCC wLUW table2 t2 [WZZZ prdicat] ... wLUWZZ LWULW : la jointure concatne les tables sans aucune correspondances de colonnes CZ1ZL colonnes 1ZLD table1 UNION wLUW table2 Il n'y a pas de critre de jointure
1Z C1 CW m m Z WUW @m2UW " 2C@mW_ C WIWUUW W C@W2mW2 WIWUUUW 1m2 12WCW2UC ZLmZL
U 1m CUmW LZL1 La clause BROUP BY est ncessaire ds que l'on utilise des fonctions de calculs statistiques avec des donnes bruts. Cette clause groupe les lignes slectionnes en se basant sur la valeur de colonnes spcifies pour chaque ligne et renvoie une seule ligne par groupe. On peut la comparer une opration de dcoupage de sous ensemble un peut la manire des "niveaux de rupture" lorsque l'on ralise des tats imprims. Cherchons compter le nombre de chambre par tage de notre htel : exemple 1 SELECT COUNT(CHB_ID) AS NOMBRE, CHB_ETAGE FROM T_CHAMBRE La requte, telle que prsente ci dessus n'est pas calculable. En effet comment dcider si le comptage doit se faire pour chaque chambre ou pour un groupe de chambre et notamment les groupes forms par chacun des tages ? Si la requte se faisait pour chaque chambre, le rsultat serait : NOMBRE CHB_ETAGE ----------- --------- 1 RDC 1 RDC 1 RDC 1 RDC 1 1er 1 1er 1 1er 1 1er 1 1er ... Et n'aurait pas beaucoup de sens ! En revanche, un regroupement par tage, donne tout son sens la requte : NOMBRE CHB_ETAGE ----------- --------- 8 1er 8 2e 4 RDC Pour raliser un tel regroupement il faut introduire une clause de groupage dans la requte. Pour cela SQL fournit le clause GROUP BY : exemple 1 (bis) SELECT COUNT(*) AS NOMBRE, CHB_ETAGE FROM T_CHAMBRE GROUP BY CHB_ETAGE WLm La prsence de la clause GROUP BY est ncessaire ds que la clause de slection, ou le filtre WHERE, ou encore les jointures comportent simultanment des calculs d'agrgation et la prsence de colonnes de table hors de calculs d'agrgation. De plus, toutes les colonnes reprsentes hors des calculs d'agrgation doivent figurer dans la clause GROUP BY La plupart du temps, le moteur de requte vous avertira d'un probable incohrence de calcul des agrgats l'aide d'un message d'erreur (avant excution de la requte), du genre : "/D FRORQQH HVW LQFRUUHFWH GDQV OD OLVWH GH VpOHFWLRQ SDUFH TXHOOH QHVW SDV FRQWHQXH GDQV XQH IRQFWLRQ GDJUpJDWLRQHWTXLOQ\DSDVGHFODXVH*5283%<" Cherchons maintenant compter le couchage de chaque tage : exemple 2 SELECT SUM(CHB_COUCHAGE) AS NOMBRE, CHB_ETAGE FROM T_CHAMBRE GROUP BY CHB_ETAGE NOMBRE CHB_ETAGE ----------- --------- 23 1er 22 2e 9 RDC Un peu plus compliqu, cherchons savoir quel a t le nombre de nuites pour chaque chambre au cours de l'anne 1999 (une nuite tant une personne passant une nuit dans une chambre. Si deux personnes occupent la mme chambre cela fait deux nuites) : exemple 3 SELECT SUM(CHB_PLN_CLI_NB_PERS), C.CHB_ID FROM T_CHAMBRE C JOIN TJ_CHB_PLN_CLI P ON C.CHB_ID = P.CHB_ID WHERE PLN_JOUR BETWEEN '1999-01-01' AND '1999-12-31' GROUP BY C.CHB_ID PERSONNE CHB_ID ----------- ----------- 558 1 385 2 322 3 367 4 445 5 720 6 390 7 456 8 362 9 364 10 529 11 468 12 347 13 360 14 484 15 720 16 491 17 372 18 504 19 369 20 Partant de la, nous pouvons rechercher le taux d'occupation de chaque chambre dans cette priode. Le nombre maximal de nuites tant le nombre de couchage de chaque chambre multipli par toutes les dates de l'anne, ce calcul s'obtient par :
exemple 4 SELECT SUM(CHB_COUCHAGE) AS MAX_OCCUPATION, CHB_ID FROM T_CHAMBRE C CROSS JOIN T_PLANNING P WHERE PLN_JOUR BETWEEN 1999-01-01 AND 1999-12-31 GROUP BY C.CHB_ID MAX_OCCUPATION CHB_ID -------------- ----------- 1095 1 730 2 730 3 730 4 1095 5 1825 6 730 7 1095 8 730 9 730 10 1095 11 1095 12 730 13 730 14 1095 15 1825 16 1095 17 730 18 1095 19 730 20 Il ne suffit plus que de "raccorder" les requtes des exemples 3 et 4 : exemple 5 SELECT (CAST(SUM(CHB_PLN_CLI_NB_PERS) AS FLOAT) / CAST(SUM(CHB_COUCHAGE) AS FLOAT)) * 100 AS TAUX_OCCUPATION_POURCENT, C.CHB_ID FROM T_CHAMBRE C JOIN TJ_CHB_PLN_CLI CPC ON C.CHB_ID = CPC.CHB_ID CROSS JOIN T_PLANNING P WHERE P.PLN_JOUR BETWEEN '1999-01-01' AND '1999-12-31' GROUP BY C.CHB_ID TAUX_OCCUPATION_POURCENT CHB_ID -------------------------- ----------- 65.293040293040292 1 74.606580829756794 2 74.64488636363636 3 74.660326086956516 4 65.301318267419958 5 60.27972027972028 6 74.759284731774414 7 67.191977077363902 8 75.878378378378372 9 75.681198910081747 10 67.715458276333777 11 65.209471766848822 12 75.920873124147334 13 74.595687331536382 14 67.343256653134858 15 61.162162162162161 16 66.891284815813108 17 77.762982689747005 18 65.900900900900908 19 76.625172890733069 20 Nous allons voir, maintenant que la clause GROUP BY est souvent utilise avec la clause HAVING... 1m CUmW mMUWL La clause HAVING agit comme le filtre WHERE, mais permet de filtrer non plus les donnes, mais les oprations rsultant des regroupements, c'est dire trs gnralement toute expression de filtre devant introduire un calcul d'agrgation. Pour tenter de comprendre l'utilit de la clause having, nous allons procder par un exemple simple : recherchons un tage de l'htel capable de coucher au moins 20 personnes. Partant de notre exemple 2, nous serions tenter d'crire : exemple 6 SELECT SUM(CHB_COUCHAGE) AS NOMBRE, CHB_ETAGE FROM T_CHAMBRE WHERE SUM(CHB_COUCHAGE) >= 20 GROUP BY CHB_ETAGE Mais cette requte va immanquablement provoquer une erreur avant excution du fait de la clause WHERE. En effet, souvenons nous que UW 2UU2W WZZZ mU 2 UW CCIIWW CW mUW et permet de filtrer ligne aprs ligne. Or le filtrage ne porte plus sur la notion de lignes, mais sur une notion de sous ensemble de la table. En d'autre termes, le filtre, ici, doit porter sur chacun des groupes. C'est pourquoi SQL introduit le filtre mMUWL qui porte, non pas sur les donnes, mais sur les calculs rsultants des regroupements. En l'occurrence, dans notre exemple, nous devons dporter le filtre WHERE dans la clause HAVING et l'opration deviendra possible : exemple 6 bis SELECT SUM(CHB_COUCHAGE) AS NOMBRE, CHB_ETAGE FROM T_CHAMBRE GROUP BY CHB_ETAGE HAVING SUM(CHB_COUCHAGE) >= 20 NOMBRE CHB_ETAGE ----------- --------- 23 1er 22 2e @ 1W C@W2mW2 WIWUUUW Cest une des parties les plus simple de lordre SELECT. A la fois par sa syntaxe mais aussi par sa comprhension facile. Il s'agit, ni plus ni moins que de raliser des oprations sur les ensembles reprsents par des tables ou des extraits de table. Les oprations ensemblistes du SQL sont l'union, l'intersection et le diffrence. @U 1WULW Pour faire une union, il suffit de disposer de deux ensembles de donnes compatibles et d'utiliser le mot clef UNION. La syntaxe est alors : SELECT ... WULW SELECT ... Bien entendu il est indispensable que les deux ordres SELECT : produisent un mme nombre de colonnes; que les types de donnes de chaque paires ordonnes de colonnes soient de mme type (ou d'un type quivalent).
@ 1UWZZCZLULW La dmarche est la mme pour faire une intersection, que pour le mcanisme de l'union. La syntaxe utilisant le mot clef INTERSECT : SELECT ... UWZZCZL SELECT ... Avec les mmes contraintes d'ordre syntaxique @@ 1m LU11ZZZWLZ La diffrence de deux ensembles s'obtient de la mme manire, en utilisant le mot clef EXCEPT : SELECT ... ZZLZ1 SELECT ...
@ m2W WC2U2W L'intersection peut tre tablie par : SELECT t1.col1, t1.col2 FROM t1 UWZZCZL SELECT t2.col1, t2.col2 FROM t2 SELECT DISTINCT t1.col1, t1.col2 FROM t1 INNER JOIN t2 ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 SELECT DISTINCT t1.col1, t1.col2 FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.col1 = t2.col1 AND t1.col2 = t2.col2) La diffrence peut tre tablie par : SELECT t1.col1, t1.col2 FROM t1 ZZLZ1 SELECT t2.col1, t2.col2 FROM t2 SELECT DISTINCT t1.col1, t1.col2 FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.col1 = t2.col1 AND t1.col2 = t2.col2) SELECT DISTINCT t1.col1, t1.col2 FROM t1 LEFT OUTER JOIN t2 ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 GROUP BY t1.col1, t1.col2 HAVING COUNT(t2.*) = 0 -- t2.* tant n'importe quelle colonne de t2
1Z C1 CW m m Z TWUW @m2UW " UW UUW m C2 CW CCIIWW UWCZZ_ 1LmZ_ LZ1ZZ 1m2 12WCW2UC ZLmZL
Il existe une diffrence fondamentale entre l'ordre de manipulation des donnes qu'est le SELECT et les diffrents ordres de mise jour de donnes : parce qu'en dehors de problmes de syntaxe ou de typage, le select est une opration dont l'aboutissement est en thorie toujours garantie (sauf indiquer des noms d'objets inexistants) alors que les oprations de mise jour des donnes sont susceptibles d'tre rejetes, notamment si elle violent des contraintes, parce qu'autant il est possible d'effectuer des extractions de donnes via un ordre SELECT sur plusieurs tables, autant il est impossible d'insrer, de modifier ou de supprimer dans plusieurs tables simultanment. parce qu'une requte de mise jour (INSERT, UPDATE ou SELECT) est une transaction en elle mme et que tout doit tre ralis, sinon rien ne se passe (en particulier si une seule donne viole une contrainte aucune insertion, mise jour ou suppression n'est effective dans le cas d'un ordre concernant la mise jour de plusieurs lignes simultanment). parce qu' moins de grer une transaction et notamment l'aide du mot clef ROLLBACK, il est impossible de revenir sur un ordre de mise jour si l'on s'est tromp. Dans le cas d'un SELECT ceci n'a pas d'importance puisque les donnes ne sont pas modifies. U UIW2W2 m UmUCW CUWCZZ
La syntaxe de base de l'ordre SQL d'insertion de donnes dans une table est la suivante :
UWCZZ [UWL] nom_de_la_table_cible [_liste_des_colonnes_visesg] {Mm1ZC _liste_des_valeursg | requte_select | LZ1m1 Mm1ZC } WLm la liste des colonnes vises peut tre omise condition que l'ordre d'insertion concerne toutes les colonnes de la table. la liste des valeurs peut tre remplace par un constructeur de lignes values pour une insertion de plusieurs lignes en un seul ordre, mais rare sont les SGBDR l'accepter (Oracle est l'un des rares SGBDR accepter cette syntaxe).
mZWULW : l'ordre des valeurs de la liste doit tre le mme que l'ordre des colonnes vises et cela, mme si la liste des colonnes vises est omise. ZZDmZZ : Du fait de sa syntaxe, l'ordre INSERT se dcompose en trois ordres assez diffrents : Insertion simple explicite; Insertion multiple explicite ( l'aide du constructeur de lignes values; Insertion base de sous requte SELECT; Insertion des valeurs par defaut Nous allons maintenant dtailler ces diffrentes dclinaisons de l'ordre INSERT... UU UIW2UCI UU@UW W2@UUCUW Cette syntaxe porte sur l'insertion d'une ligne unique au sein de la table. Il s'agit de prciser les valeurs insrer explicitement. exemple 1 INSERT INTO T_MODE_PAIEMENT (PMT_CODE, PMT_LIBELLE) VALUES ('CB' , 'Carte bancaire') Cet exemple propose d'insrer dans la table T_MODE_PAIEMENT une ligne comportant les valeurs "CB" et "Carte bancaire" dans les colonnes respectives PMT_CODE et PMT_LIBELLE. WLm : lorsqu'une valeur n'est pas connue, il est possible de prciser le mot clef NULL (marqueur) qui laisse la colonne vide. U UIW2UCI UUU@UW W2@UUCUW m UmUCW C CCI2CW2 CW UUIW MmUWW Cette syntaxe porte sur l'insertion de multiples ligne au sein de la table cible. Il faut prciser les lignes de valeurs insrer explicitement. exemple 4 INSERT T_TITRE (TIT_CODE, TIT_LIBELLE) VALUES (M. , Monsieur, Mlle. , Mademoiselle Mme. , Madame) Cet exemple propose d'insrer dans la table T_TITRE trois lignes de valeurs dans les colonnes TIT_CODE et TIT_LIBELLE. U@ UIW2UCI @m2UWUUWUWI W2@UUCUW mMWC UW UC CUW2 LZ1m1 Si la dfinition de la table possde une ou plusieurs valeurs par dfaut, alors il est possible de les y insrer en utilisant le mot clef DEFAUT en lieu et place de la valeur. Supposons que nous crons une table permettant de "pister" les connexions la base de donnes, de la manire suivante : CREATE TABLE T_SUIVI_CONNEXION (CNX_USER VARCHAR(128) NOT NULL DEFAULT 'Administrateur', CNX_DATE_HEURE TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP) Alors nous pouvons insrer l'heure et la date par dfaut sans en prciser la valeur, l'aide de la requte : exemple 6 INSERT INTO T_SUIVI_CONNEXION (CNX_USER, CNX_DATE_HEURE) VALUES ('Dupont', DEFAULT) Qui insre automatiquement la valeur par dfaut dans la colonne CNX_DATE_HEURE. U UIW2UCI CmUWUWI UU@UUCUW mMWC UW2@2WUCI LZ1m1 Mm1ZC Si chacune des colonnes de la dfinition de la table possde des valeurs par dfaut, on peut demander l'insertion de toutes les valeurs par dfaut en utilisant l'expression clef DEFAULT VALUES. Dans ce cas il ne faut pas prciser les noms des colonnes : exemple 9 INSERT INTO T_SUIVI_CONNEXION DEFAULT VALUES Qui insrera l'utilisateur 'Administrateur' avec la date et l'heure courante. C@@2WUCI m UmUCW CW LZ1ZZ La syntaxe de base de l'ordre SQL de suppression de donnes dans une table est la suivante : LZ1ZZ [1ZLD] nom_table_cible [WZZZ condition] Le seul cas pour lequel cet ordre peut ne pas aboutir est lorsque la suppression viole la contrainte d'intgrit rfrentielle. Il est en effet absurde de vouloir supprimer un client si les factures relatives ce client n'ont pas t pralablement supprimes. WLm : Dans certains cas, il se peut que la suppression d'une ligne entrane la suppressions d'autres lignes dans d'autres tables lorsque existe des intgrits rfrentielles de suppression en cascade. U @@2WUCI CW CW UW UUIW CIW mUW C'est la forme la plus simple de l'ordre DELETE puisqu'il suffit d'omettre la clause WHERE : exemple 15 DELETE FROM T_PROSPECT Supprime tous les prospects. @@2WUCI CCICUUCIIWUUW Il suffit de rajouter la clause WHERE dote d'un prdicat exemple 16 DELETE FROM T_PROSPECT WHERE PRP_PRENOM LIKE '%d' Supprime tous les prospects dont le nom se termine par la lettre 'd'. @ DCCU2UCmUCI m UmUCW C1LmZ La syntaxe de base de l'ordre SQL de modification de donnes dans une table est la suivante : 1LmZ nom_table_cible CZ colonne valeur [, colonne2 = valeur2 ...] [WZZZ condition] @U DUW m C2 CIW CCUCIIW IU@W mI CCICUUCI Cest la forme la plus simple de lordre UPDATE. Nous voulons par exemple fixer 55 F les tarifs de nos petits djeuners dans la table T_TARIF : exemple 19 UPDATE T_TARIF SET TRF_PETIT_DEJEUNE = 55 @ DUW m C2 CIW CCUCIIW IU@W mMWC 2W@2UW CW MmUW2 _mC 2W2W2WICWg On peut aussi reprendre la valeur de la colonne (ou d'une autre colonne de la table cible). Par exemple nous pouvons demander une augmentation de 15% des tarifs des petits djeuners : exemple 20 UPDATE T_TARIF SET TRF_PETIT_DEJEUNE = TRF_PETIT_DEJEUNE * 1.15 @@ DUW m C2 CIW CCUCIIW IU@W mMWC 2UU2mW On peut ajouter une clause de filtrage WHERE dans une requte de mise jour. Par exemple nous pouvons dcider de n'augmenter de 15% que les tarifs des petits djeuners des priodes postrieures 1999 exemple 21 UPDATE T_TARIF SET TRF_PETIT_DEJEUNE = TRF_PETIT_DEJEUNE * 1.15 WHERE EXTRACT(YEAR FROM TRF_DATE_DEBUT) > 1999 @ DUW m C2 CW @UUW2 CCUCIIW UUUmIWUWI Pour mettre jour simultanment plusieurs colonnes, il suffit de rpter autant de fois que ncessaire le contenu de la clause SET, raison d'un couple colonne/valeur par colonne vises par la mise jour. exemple 22 UPDATE T_CLIENT SET CLI_NOM = UPPER(CLI_NOM), CLI_PRENOM = UPPER(CLI_PRENOM) CLI_ENSEIGNE = UPPER(CLI_ENSEIGNE) WLm : dans ce cas, la nullit de l'excution de modification d'une valeur dans une colonne possdant le marqueur NULL, n'entrane pas la nullit de l'excution des mises jour des autres colonnes, chaque modification de colonne tant values sparment.
@C DUW m C2 mMWC C 2W@WW Comme dans les ordres INSERT et DELETE, il est possible d'utiliser une sous requte dans la clause WHERE de l'ordre UPDATE afin de filtrer de manire plus complte. Par exemple, afin d'viter de confondre des prospects qui ont le mme nom et prnom que certains client, on dsire ajouter le mot "bis" aux prospects homonymes : exemple 23 UPDATE T_PROSPECT SET PRP_NOM = TRIM(RIGHT, PRP_NOM) || ' bis' WHERE PRP_ID = (SELECT PRP_ID FROM T_PROSPECT P JOIN T_CLIENT C ON C.CLI_NOM = P.PRP_NOM AND C.CLI_PRENOM= P.PRP_PRENOM) mZWULW : Une mise jour peut chouer si elle viole les contraintes. Voici les principaux cas pour lesquels un ordre de modification ne peut aboutir : violation de clef (index primaire) violation de contrainte d'index secondaire unique violation de contrainte de donnes (colonne not null) violation d'intgrit rfrentielle violation de contrainte de contrle de validit (min, max, tendue, domaine...)