IN306 : Corrigé SID Christophe Garion <garion@isae.fr> 18 octobre 2010 Ce document est un corrigé succinct de l examen du module IN306. 1 Modélisation d une base de données pour une société de bourse Une société de bourse vous confie la charge de la conception de sa base de données permettant de gérer un ensemble d informations pour ses analystes comme pour ses clients : gestion des portefeuilles, historique des cours, passation d un ordre etc. Un titre est caractérisé par un libellé, un code (appelé code sicovam et unique) et l historique de ses cours. Un cours est la valeur du titre à une date donnée. On suppose qu un titre ne peut avoir qu un cours par jour. La valeur courante (cours du marché) du titre est le dernier de l historique. Deux types de titres sont gérés par la société de bourse : l action : elle représente une part du capital d une société. Elle donne droit à son propriétaire en fin d année à un revenu appelé dividende (ce dividende est variable car son montant est déterminé chaque année par le conseil d administration de la société). l obligation : elle représente un emprunt effectué par un organisme à un taux d intérêt donné. Sa valeur nominale est la valeur du titre à l achat. C est la valeur qui sera remboursée par l organisme au souscripteur à l échéance de l emprunt, si le souscripteur n a pas vendu l obligation avant au cours du marché. Un titre ne peut être qu une action ou une obligation. Chaque client doit donner lors de l ouverture d un compte ses coordonnées postales et bancaires (RIB) et une adresse e-mail qui permettent de l identifier. Il peut être conseillé par un courtier qui lui est attaché lors de l ouverture du compte. Le courtier et les clients ont les mêmes caractéristiques : coordonnées postales, adresse mail. Le client a un RIB et des portefeuilles en plus. Chaque client possède un certain nombre de portefeuilles. Un portefeuille est caractérisé par un nom unique(donné par le client) et un ensemble d avoirs. Un avoir correspond a une certaine quantité de titres identiques (de même code) possédé par le client. Un avoir est caractérisé par un prix d achat global (somme des prix d achat de chaque titre) et la plus/moins value réalisée (delta avec la valeur courante des titres). 1. proposer un diagramme entité-association correspondant au cahier des charges précédent (avec cardinalités et rôles) ; Une proposition de corrigé est présenté sur la figure 1 Quelques remarques sur le modèle proposé : pas de problèmes particulier pour l entité Titre. en ce qui concerne l entité Cours, on trouve facilement ses attributs. Elle est liée à Titre par l association Historique. Pour la valeur courante du titre, il suffit de trouver le cours le plus récent. Par contre, on ne peut pas identifier un cours simplement par sa valeur et sa date : il se peut que plusieurs titres aient la même valeur au même moment. On ne pourra l identifier qu en utilisant le titre associé par Historique : on parle alors d entité faible (représentée par un double rectangle). On suppose par contre qu une date suffit pour «identifier» un cours. l entité Avoir est une entité faible : on est obligé de connaître le titre auquel il est associé. J ai choisi ici d introduire un attribut quantité dans Avoir, ce qui amène une multiplicité [1,1] du côté de Avoir. Sans cet attribut, la multiplicité aurait été [1,n]. 1
pour la modélisation des entités Action et Obligation, on se heurte au manque d expressivité du modèle entité-association : il s agit en effet d une relation d héritage... J ai donc choisi de reporter le problème en considérant qu on émettra des contraintes suffisamment fortes pour modéliser le problème. Ici, on voit qu un tuple de titre peut être associé à un tuple de Action et peut être lié à un tupe de Obligation. Il faut donc ajouter une contrainte spécifiant qu un titre est obligatoirement associé à une action ou une obligation, car rien n empêche avec ce diagramme d avoir un titre qui n est lié ni à une action, ni à une obligation. Obligation reste par contre une entité faible, car un même organisme peut émettre plusieurs obligations. pas de problèmes pour les entités Portefeuille, Client et Courtier, ainsi que pour les associations les liant. Tous les problèmes d entités faibles pouvaient être également résolus en introduisant des numéros d identifiants uniques pour Cours, Avoir etc. Cependant, l introduction de tels identifiants peut poser des problèmes pour l identification des dépendances fonctionnelles, en particulier pour les dépendances fonctionnelles transitives. 2. proposer un modèle relationnel correspondant au schéma entité/association de la question 1. Nous allons utiliser l algorithme vu en cours pour «transformer» le modèle E/A en modèle relationnel. Le problème des entités faibles sera rapidement réglé : on introduira les clés primaires des entités en relation avec les entités faibles permettant de les identifier. Le problème de la spécialisation de Titre se réglera via des contraintes. On obtient alors les relations suivantes : Courtier (adresse mail, adresse postale) Client (adresse mail, adresse postale, RIB, courtier) Portefeuille (nom, client) Titre (sicovam, libelle) Cours (sicovam, date, valeur) Action (societe, dividende, sicovam) Obligation (sicovam, organisme, valeur) Avoir (sicovam, portfeuille, quantite, prix global, delta) Les contraintes de clés étrangères sont les suivantes : Client(courtier) référence Courtier(adresse mail) Portefeuille(client) référence Client(adresse mail) Cours(sicovam) référence Titre(sicovam) Action(sicovam) référence Titre(sicovam) Obligation(sicovam) référence Titre(sicovam) Avoir(portefeuille) référence Portefeuille(nom) Avoir(sicovam) référence Titre(sicovam) 3. comment vérifier que les relations du schéma relationnel proposé en question 2 est 3NF? On suppose que les relations sont 1NF (i.e. que les domaines des attributs sont uniques, même pour l adresse postale par exemple). On voit qu elle est en 2NF : les clés primaires des relations sont en dépendance élémentaire avec les attributs. 2
Est-ce que les relations sont en 3NF? Pour cela, il faut examiner s il n existe pas d attribut d une relation dépendant fonctionnellement d un attribut non clé. On pourra vérifier qu il n en existe pas. 4. Jérôme K., un analyste futur utilisateur de votre système, soulève la question suivante : sachant que les courtiers ne peuvent engager qu un montant global maximum par jour (achat d avoirs), quelle solution simple proposez-vous pour que cette contrainte soit implantée dans la base? Une solution simple est d implanter un trigger qui vérifie que lorsqu un courtier passe un ordre d achat le montant global d achat d avoirs qu il a engagé pour la journée ne dépasse pas le montant maximum autorisé. 2 Une base de données de jolis navions 1 On considère une base de données relationnelle implantée dans une compagnie aérienne et permettant de gérer des vols, des pilotes et des avions. Son schéma est le suivant : Pilote (num pil, nom, adresse, salaire) Avion (num avion, nom, capacite, localisation) Vol (num vol, num avion, num pil, ville dep, ville arr, h dep, h arr) Les contraintes de clés étrangères sont les suivantes : Vol(num avion) référence Avion(num avion) Vol(num pil) référence Pilote(num pil) On considère les requêtes suivantes : 1. quels sont les pilotes ne pilotant que des avions de plus de 300 places? 2. quels sont les pilotes toulousains ne conduisant que des avions arrivant au moins une fois à Toulouse? 3. quel est le salaire maximum d un pilote parisien? 4. quel est le salaire maximum d un pilote et quels sont les pilotes qui le perçoivent? 5. quelle est la localisation des avions qui font un aller mais pas le retour (sur la ville de départ)? 6. quelle est la localisation des avions qui ne font que des trajets avec le retour sur la ville de départ de l aller? Questions : 1. exprimer les requêtes 1 et 2 en algèbre relationnelle ; On pourra remarquer que l on pouvait utiliser des jointures naturelles, car les attributs avaient les mêmes noms dans les différentes relations. Voici la requête 1 exprimée en algèbre relationnelle : π num pil (Vol) π num pil (σ capacite<300 (Vol Avion)) Rien de bien difficile. Il ne fallait pas oublier le «que des avions de plus de 300 places» : cela imposait de trouver d abord les pilotes qui pilotent des avions de moins de 300 places et de faire la 1. Ben oui, fallait bien que ça arrive un jour ou l autre à SUPAERO... 3
différence avec l ensemble des pilotes. J ai choisi d utiliser la relation Vol pour ne sélectionner que les pilotes qui volent effectivement. Voici la requête 2 exprimée en algèbre relationnelle : π num pil (σ adresse= Toulouse (P ilote)) π num pil (π num avion (Avion) (π num avion (σ ville arr= Toulouse (Vol) Avion))) Pilote Vol) Quelques explications : π num avion (σ ville arr= Toulouse (Vol) Avion) donne les numéros d avions qui atterrissent au moins une fois à Toulouse ; π num avion (Avion) (π num avion (σ ville arr= Toulouse (Vol) Avion)) donne les numéros d avions qui n atterrissent jamais à Toulouse ; π num pil (π num avion (Avion) (π num avion (σ ville arr= Toulouse (Vol) Avion))) Pilote Vol) donne les numéros de pilotes qui pilotent un avion qui n atterrit jamais à Toulouse ; il suffit ensuite d enlever les numéros de pilotes trouvés à l étape précédente aux numéros de pilotes toulousains pour trouver la réponse à la question. 2. exprimer les requêts 1 à 6 en SQL. Si l on veut réutiliser le résultat d une requête d une question à l autre, on pourra utiliser des alias (par exemple : le résultat de la requête 5 sera noté T dans cette question). Voici la requête 1 exprimée en SQL : 1 (SELECT num_pil 2 FROM Vol) 3 EXCEPT 4 (SELECT num_pil 5 FROM Vol NATURAL JOIN Avion 6 WHERE capacite < 300); Rien de bien compliqué, j ai utilisé la requête exprimée en algèbre relationnelle pour construire la requête SQL. Voici la requête 2 exprimée en SQL : 1 SELECT num_pil 2 FROM Pilote 3 WHERE (adresse = Toulouse ) AND 4 (num_pil NOT IN 5 (SELECT num_pil 6 FROM Vol 7 WHERE num_av NOT IN 8 (SELECT num_av FROM Vol WHERE ville_arr = Toulouse ))); J ai préféré utiliser ici l opérateur NOT IN de SQL qui permet de trouver les avions n atterrissant pas une fois à Toulouse, puis les pilotes ne pilotant un de ces avions. Voici la requête 3 exprimée en SQL : 1 SELECT MAX(salaire) 2 FROM Pilote 3 WHERE adresse = Paris ; 4
Rien de bien difficile ici. Voici la requête 4 exprimée en SQL : 1 SELECT num_pil, salaire 2 FROM Pilote 3 WHERE salaire = (SELECT MAX(salaire) FROM Pilote); Rien de bien difficile ici. Voici la requête 5 exprimée en SQL : 1 SELECT localisation 2 FROM (SELECT localisation, num_av, ville_dep, ville_arr 3 FROM Avion NATURAL JOIN Vol AS T 4 WHERE NOT EXISTS ( 5 SELECT num_av, ville_dep, ville_arr 6 FROM Avion NATURAL JOIN Vol 7 WHERE (num_av = T.num_av) AND 8 (ville_dep = T.ville_arr) AND 9 (ville_arr = T.ville_dep))); Il s agissait de la requête la plus difficile. Je vais la détailler. La ligne 1 est juste là pour n obtenir que la localisation. Les lignes 2 et 3 permettent de sélectionner les numéros d avion avec les villes de départ et d arrivée et je nomme cette relation T. On peut (cf. corrigé des exercises sur SQL faits en cours) utiliser ensuite la variable T dans la clause WHERE pour faire une comparaison avec les vols qui ont pour ville de départ celle d arrivée du tuple de T considéré et pour ville d arrivée la ville de départ de T (cf. lignes 5 à 9). Voici la requête 6 exprimée en SQL : 1 CREATE VIEW R AS 2 SELECT localisation 3 FROM (SELECT localisation, num_av, ville_dep, ville_arr 4 FROM Avion NATURAL JOIN Vol AS T 5 WHERE NOT EXISTS ( 6 SELECT num_av, ville_dep, ville_arr 7 FROM Avion NATURAL JOIN Vol 8 WHERE (num_av = T.num_av) AND 9 (ville_dep = T.ville_arr) AND 10 (ville_arr = T.ville_dep))); 11 12 SELECT localisation 13 FROM Avion 14 WHERE localisation NOT IN (SELECT * FROM R); Rien de bien difficile en utilisant la requête précédente que j ai appelée R. 5
[1,1] [1,1] Action est une [1,1] est une Obligation société dividende [0,1] [0,1] organisme valeur [1,1] [1,n] Avoir est composé Titre [1,n] [1,1] historique Cours quantité prix global delta sicovam libellé valeur date est composé [1,n] [1,1] [1,n] Portefeuille possède Client [1,1] [1,n] conseille Courtier nom adresse mail adresse postale RIB adresse mail adresse postale Figure 1 : Proposition de diagramme E/A 6