1. Trang chủ
  2. » Công Nghệ Thông Tin

Pratique de MySQL et PHP- P87 potx

5 269 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 130,83 KB

Nội dung

408 Chapitre 10. Récapitulatif SQL Notez la syntaxe table.* qui représente tous les attributs de la table table.On peut considérer que la jointure est moins naturelle, et que la requête imbriquée est plus proche de la manière dont la recherche est conçue : on ne s’intéresse pas directement aux films de Clint Eastwood, mais seulement aux rôles. Il n’en reste pas moins que toutes deux donnent le même résultat. Autre exemple : donner les films pour lesquels on connaît au moins un des rôles. On peut utiliser une requête imbriquée. SELECT * FROM Film WHERE titre IN (SELECT titre FROM Role) On va donc parcourir les films, et pour chacun, on affichera son titre si et seulement si ce titre apparaît dans au moins une des lignes de la table Role.Onpeut là aussi utiliser une jointure. SELECT DISTINCT Film.* FROM Film, Role WHERE Film.titre = Role.titre Il y a une différence un peu subtile : avec la jointure on affichera autant de fois un titre qu’il y a de rôles. Le mot-clé DISTINCT permet de se ramener à un résultat équivalent à celui de la requête imbriquée. On peut exprimer la condition d’appartenance sur des lignes comprenant plu- sieurs attributs, comme le montre la requête suivante : on recherche tous les films du même genre qu’Impitoyable, et sont parus la même année. SELECT * FROM Film WHERE (annee, genre) = (SELECT annee, genre FROM Film f WHERE titre=’Impitoyable’) Le nombre et le type des attributs (ici deux attributs) doit correspondre exacte- ment dans la requête principale et la requête imbriquée. Bien entendu la requête ci-dessus s’exprime avec une jointure. Ce n’est pas le cas en revanche de celle ci-dessous, qui sélectionne l’artiste avec la date de naissance la plus ancienne. SELECT prenom, nom FROM Artiste WHERE annee_naissance <= ALL (SELECT annee_naissance FROM Artiste WHERE annee_naissance IS NOT NULL) AND annee_naissance IS NOT NULL; + + + | prenom | nom | + + + | Akira | Kurosawa | + + + 10.4 Requêtes imbriquées 409 Le ALL exprime une comparaison qui vaut pour toutes les lignes ramenées par la requête imbriquée. Attention aux valeurs à NULL dans ce genre de situation : toute comparaison avec une de ces valeurs renvoie UNKNOWN et cela peut entraîner l’échec du ALL. Il n’existe pas d’expression avec jointure qui puisse exprimer ce genre de condition. En revanche, le ALL peut s’exprimer avec la négation, selon la règle d’équivalence que quand quelque chose est toujours vrai, il n’est jamais faux ! Nous verrons un exemple plus loin. 10.4.2 Requêtes corrélées Les exemples de requêtes imbriquées donnés précédemment pouvaient être évalués indépendamment de la requête principale, ce qui permet au système (s’il le juge nécessaire) d’exécuter la requête en deux phases. La clause EXISTS fournit encore un nouveau moyen d’exprimer les requêtes vues précédemment, en basant la sous- requête sur une ou plusieurs valeurs issues de la requête principale. On parle alors de requêtes corrélées. Reprenons une dernière fois la requête donnant les rôles des films de Clint Eastwood. Elle s’exprime avec EXISTS de la manière suivante : SELECT * FROM Role WHERE EXISTS (SELECT titre FROM Film, Artiste WHERE Film.id_realisateur=Artiste.id AND Film.titre=Role.titre AND nom=’Eastwood’) + + + + | titre | id_acteur| nom_role | + + + + | Impitoyable | 20 | William Munny | | Impitoyable | 21 | Little Bill Dagget | | Les pleins pouvoirs | 21 | Le pr´esident | + + + + On obtient donc une nouvelle technique d’expression, qui permet d’aborder le critère de recherche sous une troisième perspective : on conserve un rôle si, pour ce rôle, le film a été dirigé par Clint Eastwood. Notez la jointure entre la table Role référencée dans la requête principale et la table Film de la requête imbriquée. C’est cette comparaison « à distance » entre deux tables référencées par des clauses FROM différentes qui explique le terme de corrélation. Supposons que l’on veuille trouver tous les metteurs en scène ayant dirigé Gene Hackman. La requête peut s’exprimer avec EXIST de la manière suivante : SELECT * FROM Artiste a1 WHERE EXISTS (SELECT * FROM Film f, Role r, Artiste a2 WHERE f.titre = r.titre AND r.id_acteur = a2.id 410 Chapitre 10. Récapitulatif SQL AND nom = ’Hackman’ AND f.id_realisateur = a1. id) + + + + + | id | nom | prenom | annee_naissance | + + + + + | 20 | Eastwood | Clint | 1930 | + + + + + En langage naturel, le raisonnement est le suivant : on prend tous les artistes (requête principale) tels que, parmi les films qu’ils ont dirigés (requête secondaire), on trouve un rôle joué par Gene Hackman. REMARQUE – dans une sous-requête associée à la clause EXISTS, peu importent les attributs du SELECT puisque la condition se résume à : cette requête ramène-t-elle au moins une ligne ou non ? On peut donc systématiquement utiliser SELECT *. La requête équivalente avec IN s’appuie sur un raisonnement légèrement modifié : on prend tous les artistes dont l’identifiant fait partie de l’ensemble des identifiants des metteurs en scène d’un film avec Gene Hackman. SELECT * FROM Artiste a1 WHERE id IN (SELECT id_realisateur FROM Film f, Role r, Artiste a2 WHERE f.titre = r.titre AND r.id_acteur = a2.id AND nom = ’Hackman’) La solution classique d’une jointure « à plat » reste valable, en utilisant DISTINCT pour éliminer les doublons : SELECT DISTINCT a1.* FROM Artiste a1, Film f, Role r, Artiste a2 WHERE f.titre = r.titre AND r.id_acteur = a2.id AND a2.nom = ’Hackman’ AND f.id_realisateur = a1. id Enfin, rien n’empêche d’utiliser plusieurs niveaux d’imbrication ! SELECT * FROM Artiste a1 WHERE EXISTS (SELECT * FROM Film f WHERE f.id_realisateur = a1. id AND EXISTS (SELECT * FROM Role r WHERE f.titre = r.titre AND EXISTS (SELECT * FROM Artiste a2 WHERE r.id_acteur = a2.id AND nom = ’Hackman’))) 10.4 Requêtes imbriquées 411 Je laisse le lecteur déchiffrer cette dernière requête (elle fonctionne !) et se convaincre que l’argument de lisibilité des requêtes imbriquées atteint rapidement ses limites. De plus ce genre d’expression sera probablement plus difficile à traiter pour le système. En résumé, une jointure entre les tables R et S de la forme : SELECT R.* FROM R, S WHERE R.a = S.b peut s’écrire de manière équivalente avec une requête imbriquée : SELECT * FROM R WHERE R.a IN (SELECT S.b FROM S) ou bien encore sous forme de requête corrélée : SELECT * FROM R WHERE EXISTS (SELECT S.b FROM S WHERE S.b = R.a) Le choix de la forme est matière de goût ou de lisibilité, ces deux critères relevant de considérations essentiellement subjectives. 10.4.3 Requêtes avec négation Les requêtes imbriquées sont en revanche irremplaçables pour exprimer des négations. On utilise alors NOT IN ou (de manière équivalente) NOT EXISTS. Voici un premier exemple avec la requête : donner les films pour lesquels on ne connaît aucun rôle. SELECT * FROM Film WHERE titre NOT IN (SELECT titre FROM Role); On obtient le résultat suivant : + + + + + | titre | annee | id_realisateur | genre | + + + + + | Kagemusha | 1980 | 68 | Drame | + + + + + La négation est aussi un moyen d’exprimer des requêtes courantes comme celle recherchant le (ou les) films le(s) plus ancien(s) de la base. En SQL, on utilisera typiquement une sous-requête pour prendre l’année minimale parmi les années de production des films, laquelle servira à sélectionner un ou plusieurs films. 412 Chapitre 10. Récapitulatif SQL SELECT * FROM Film WHERE annee = (SELECT MIN(annee) FROM Film) Il existe en fait beaucoup de manières d’exprimer la même chose avec un SQL « complet ». Tout d’abord cette requête peut en fait s’exprimer sans la fonction MIN(), avec la négation: si f est le film le plus ancien, c’est en effet qu’il n’existe pas de film strictement plus ancien que f. On utilise alors habituellement une requête dite « corrélée » dans laquelle la sous-requête est basée sur une ou plusieurs valeurs issues des tables de la requête principale. SELECT * FROM Film f1 WHERE NOT EXISTS (SELECT annee FROM Film f2 WHERE f1.annee > f2.annee) Le f1.annee dans la requête imbriquée appartient à la table référencée dans le FROM de la requête principale. Autre manière d’exprimer la même chose : si un film est le plus ancien, tous les autres sont plus récents. On peut utiliser le mot-clé ALL, qui indique que la comparaison est vraie avec tous les éléments de l’ensemble constitué par la sous-requête. SELECT * FROM Film WHERE annee <= ALL (SELECT annee FROM Film) On préfère en général NOT EXISTS à ALL, mais les deux sont équivalents, puisque quand une propriété est vraie pour tous les éléments d’un ensemble, il n’existe pas d’élément pour lequel elle est fausse. Dernier exemple de négation : quels artistes ne sont pas metteur en scène ? Les deux formulations ci-dessous sont équivalentes, l’une s’appuyant sur NOT IN et l’autre sur NOT EXISTS. SELECT * FROM Artiste WHERE id NOT IN (SELECT id_realisateur FROM Film) SELECT * FROM Artiste WHERE NOT EXISTS (SELECT * FROM Film WHERE Artiste.id = Film.id_realisateur) Dans les deux cas, on trouve le résultat suivant : + + + + + | id | nom | prenom | annee_naissance | + + + + + | 21 | Hackman | Gene | 1930 | | 30 | Dutronc | Jacques | NULL | + + + + + . le lecteur déchiffrer cette dernière requête (elle fonctionne !) et se convaincre que l’argument de lisibilité des requêtes imbriquées atteint rapidement ses limites. De plus ce genre d’expression. requête principale et la table Film de la requête imbriquée. C’est cette comparaison « à distance » entre deux tables référencées par des clauses FROM différentes qui explique le terme de corrélation. Supposons. raisonnement légèrement modifié : on prend tous les artistes dont l’identifiant fait partie de l’ensemble des identifiants des metteurs en scène d’un film avec Gene Hackman. SELECT * FROM Artiste

Ngày đăng: 06/07/2014, 00:20

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN