PROJET de BD Licence 6 juin 2003 version 1.0 Benoit Bourdin / Stephane Poinsart / Samnang Traing enseignante: Veronique Ventos 1
1 Création de la base 1.1 Schema Lors de la conception des requetes, nous avons oublié quelques détails dans le schéma. Cependant il ne s agit bien sûr que de modifications mineures, qui n impliquent pas une modification ou ajout d une table. Fig. 1 Modèle entité-association 1.2 Création Suite au schéma, il a fallu créer les tables effectivement en SQL. Pour ce faire, il a fallu faire un script de création. Nous avons donc traduit le schéma de façon concrète, et donc supprimé les associations : 2
Associations 1 - n : on ajoute un attribut du coté du n. Associations n - n : on ajoute une table intermédiaire contenant 2 attributs. Associations ternaires : on ajoute une table contenant les 3 attributs en question. Dans les 3 cas, on prendra comme nom d attribut les noms des associations. Par la suite on présente donc le script de création de la base. Tout d abord il est bon de supprimer les tables avant de les créer. DROP TABLE caserne; DROP TABLE pompier; DROP TABLE distance; DROP TABLE adresse; DROP TABLE fabriquant; DROP TABLE ville; DROP TABLE modelecamion; DROP TABLE camion; DROP TABLE citerne; DROP TABLE protege; Pour la numérotation, on utilise les séquences en PostgreSQL, ce qui permet de ne pas se soucier du numéro en insérant. DROP SEQUENCE seq_casnum; DROP SEQUENCE seq_pomnum; DROP SEQUENCE seq_camnum; DROP SEQUENCE seq_adrnum; CREATE SEQUENCE seq_casnum; CREATE SEQUENCE seq_pomnum; CREATE SEQUENCE seq_camnum; CREATE SEQUENCE seq_adrnum; On crée enfin les tables proprement dites. CREATE TABLE caserne( numero integer DEFAULT nextval( seq_casnum ) NOT NULL PRIMARY KEY, hommesmax integer NOT NULL, camionsmax integer NOT NULL, siege integer NOT NULL CREATE TABLE protege( 3
casnum integer NOT NULL, nomville varchar(64) NOT NULL CREATE TABLE pompier( numero integer DEFAULT nextval( seq_pomnum ) NOT NULL PRIMARY KEY, nom varchar(32) NOT NULL, travaille integer NOT NULL, habite integer NOT NULL CREATE TABLE distance( addr integer NOT NULL, cas integer NOT NULL, distance integer NOT NULL CREATE TABLE adresse( numero integer DEFAULT nextval( seq_adrnum ) NOT NULL PRIMARY KEY, numerorue integer NOT NULL, rue varchar(256) NOT NULL, ville varchar(64) NOT NULL, codepostal integer NOT NULL CREATE TABLE fabriquant( marque varchar(64) NOT NULL PRIMARY KEY, addr integer NOT NULL, delailivraison integer NOT NULL CREATE TABLE ville( nom varchar(64) NOT NULL PRIMARY KEY, nbhabitants integer NOT NULL CREATE TABLE modelecamion( nom varchar(64) NOT NULL PRIMARY KEY, type varchar(64) NOT NULL, moteur varchar(64) NOT NULL, fabrique varchar(64) NOT NULL 4
CREATE TABLE camion( numero integer DEFAULT nextval( seq_camnum ) NOT NULL PRIMARY KEY, places integer NOT NULL, modele varchar(64) NOT NULL, stoque integer NOT NULL CREATE TABLE citerne( numero integer NOT NULL PRIMARY KEY, contenance integer NOT NULL Dans la suite du script on a aussi des commandes de gestion de droit (GRANT ALL ON <table> to <utilisateur>) pour partager les droits sur les tables en question aux autres personnes du trinome. On remarquera que ce script ne déclare aucune contrainte (notamment, d intégrité référentielles) à part le fait que les attributs valent NULL ou pas. 1.3 Remplissage Une fois les tables crées, il est utile de les remplir. Cette opération a elle aussi été réalisée par un script. Cependant, il n est pas nécessaire de le détailler étant donné la simplicité de la chose. On signalera juste pour les séquences on aura par exemple : INSERT INTO caserne(hommesmax, camionsmax, siege) VALUES (50, 20, 1 On donne toutefois le résultat des tables une fois créees et remplies : => SELECT * from camion ; numero places modele stoque --------+--------+------------------+-------- 1 15 Maximus610 2 2 12 Maximus410 2 3 5 Vroom500 2 4 20 PimpomIIzeRetour 4 5 20 PimpomIIzeRetour 4 6 15 PimpomIIzeRetour 2 7 12 PimpomI 2 5
8 30 PimpomIIXXLC 2 9 30 Maximus610 3 10 12 PimpomI 3 11 60 Vroom600 5 => SELECT * from caserne; numero hommesmax camionsmax siege --------+-----------+------------+------- 1 4 3 1 2 23 5 3 3 30 9 4 4 12 3 8 5 12 3 9 6 1 64 10 => SELECT * from citerne; numero contenance --------+------------ 1 1500 4 2500 5 2500 7 1500 8 800 11 800 => SELECT * from distance; addr cas distance ------+-----+---------- 2 1 3 3 1 30 4 1 35 5 1 2 6 2 7 7 2 8 8 2 25 9 2 40 10 2 6 6 3 13 7 3 15 8 3 10 10 4 14 6
11 4 12 14 4 14 15 4 12 17 4 12 1 5 12 2 5 19 3 5 2 1 6 5 2 6 8 3 6 10 => SELECT * from fabriquant; marque addr delailivraison ---------+------+---------------- Pegot 16 15 Citroen 17 7 Renault 18 10 => SELECT * from modelecamion ; nom type moteur fabrique ------------------+--------+--------+---------- Premieum210 lourd 210hp Pegot Premieum410 lourd 410hp Pegot Maximus610 lourd 610hp Pegot Minimus210 rapide 21hp Pegot Minimum410 rapide 41hp Pegot Vroom500 rapide 250hp Citroen Vroom600 rapide 300hp Citroen PimpomI rapide 100hp Renault PimpomIIzeRetour rapide 200hp Renault PimpomIIXXLC lourd 500hp Renault => SELECT * from pompier ; numero nom travaille habite --------+----------+-----------+-------- 1 Bennyben 2 5 2 Mikomi 6 10 3 Ste 2 17 4 Toto 1 11 5 Gattes 6 12 6 Dupont 2 14 7
7 Dupond 3 15 8 Torvalds 4 4 9 Cox 5 5 => SELECT * from protege ; casnum nomville --------+-------------- 1 Brignoles 2 Brignoles 4 Brignoles 1 Le Luc 3 Le Luc 1 Draguignan 3 Draguignan 4 Draguignan 5 VieuxPCVille 6 PiVille 6 EpitaVillage => SELECT * from ville ; nom nbhabitants --------------+------------- Draguignan 35800 Le Luc 4350 Brignoles 35000 PoliceCT 22 VieuxPCVille 386 PiVille 31416 EpitaVillage 42 8
2 Requêtes Pour l ensemble des requêtes données, on donnera donc à la fois en SQL et en algèbre relationnel. On affichera ensuite le résultat. Dans le cas de l algèbre relationnel, on ne précisera les jointures que lorsqu il y a une ambiguité. Concernant les distances, on considère qu il n y a dans notre base que quelques distances, les seules précisant les casernes les plus proches d une ville donnée. Si jamais il existe une ou des casernes dans la ville donnée, la distance sera 0, mais l enregistrement sera présent. 2.1 requête a Quels sont les pompiers des casernes situées à Draguignan? 2.1.1 Algèbre relationnel Π p.nom,p.numero (σ ad.ville= Draguignan (pompier p caserne cs adresse ad) 2.1.2 SQL SELECT pompier.numero, pompier.nom, pompier.travaille FROM pompier, caserne, adresse WHERE travaille=caserne.numero AND caserne.siege = adresse.numero AND adresse.ville= Draguignan ; 2.1.3 Résultat numero nom travaille --------+----------+----------- 1 Bennyben 2 3 Ste 2 4 Toto 1 6 Dupont 2 2.2 requête b Quelles sont les casernes protégeant à la fois Brignoles et Le Luc? 2.2.1 Algèbre relationnel (Π numero (σ nomville= LeLuc (caserne protege))) (Π numero (σ nomville= Brignoles (caserne protege))) 9
2.2.2 SQL (SELECT numero FROM caserne,protege WHERE protege.casnum=caserne.numero AND nomville= Le Luc ) INTERSECT (SELECT numero FROM caserne,protege WHERE protege.casnum=caserne.numero AND nomville= Brignoles 2.2.3 Résultat numero -------- 1 2.3 requête c Quels sont les camions protégeant la ville de Brignoles? 2.3.1 Algèbre relationnel Π numero,places,modele,stoque ( σ ville.nom= Brignoles (camion caserne protege ville)) 2.3.2 SQL SELECT c.* FROM camion c, caserne s, ville v, protege p WHERE c.stoque=c.numero AND c.stoque=s.numero AND s.numero=p.casnum AND p.nomville=v.nom AND v.nom= Brignoles ; 2.3.3 Résultat numero places modele stoque --------+--------+------------------+-------- 2 12 Maximus410 2 4 20 PimpomIIzeRetour 4 10
2.4 requête d Quels sont les pompiers de la caserne 3 habitant à plus de 5kms d une caserne? 2.4.1 Algèbre relationnel On considère ici que l on a toutes les informations dans la table distance pour effectuer la requete. Cela implique que pour chaque adresse de pompier, on aie les distances par rapport aux plus proches casernes. Π p.numero,p.nom,d.distance ( σ p.travaille=3 p.habite=d.addr (pompier p caserne cs distance d) 2.4.2 SQL SELECT pompier.numero, pompier.nom, distance FROM pompier, distance, caserne WHERE travaille=3 AND pompier.habite=distance.addr AND caserne.numero=cas AND distance>5; 2.4.3 Résultat numero nom distance --------+--------+---------- 7 Dupond 12 2.5 requête e Quels sont les pompiers habitant Le Luc ou des villes 20 000 h? 2.5.1 Algèbre relationnel Π numero,nom,travaille,habite ( σ ville.nbhabitants 20000 ville.nom= LeLuc (pompier adresse ville)) 2.5.2 SQL SELECT pompier.* FROM pompier, adresse, ville WHERE pompier.habite=adresse.numero AND adresse.ville=ville.nom AND (ville.nbhabitants>=20000 or ville.nom= Le Luc 11
2.5.3 Résultat numero nom travaille habite --------+----------+-----------+-------- 8 Torvalds 4 4 1 Bennyben 2 5 9 Cox 5 5 4 Toto 1 11 5 Gattes 6 12 6 Dupont 2 14 7 Dupond 3 15 3 Ste 2 17 2.6 requête f Quel est le délai de livraison des fabriquants de citernes de moins de 1000 litres? 2.6.1 Algèbre relationnel Π marque,addr,delailivraison ( σ citerne.contenance<1000 (fabriquant modelecamion camion citerne)) 2.6.2 SQL SELECT f.* FROM fabriquant f, citerne ci, camion ca, modelecamion mc WHERE f.marque=mc.fabrique AND mc.nom=ca.modele AND ca.numero=ci.numero AND ci.contenance<1000; 2.6.3 Résultat marque addr delailivraison ---------+------+---------------- Citroen 17 7 Renault 18 10 2.7 requête g Quelles sont les casernes dont tous les pompiers habitent à plus de 5kms? 12
2.7.1 Algèbre relationnel On considère ici qu on a bien tout ce qu il faut dans la table distance. Cela implique donc qu on aura, pour chaque pompier d une caserne donnée, sa distance par rapport à la caserne où il travaille. Etant donné l énoncé, cela implique donc qu un pompier travaille toujours dans une des casernes les plus proches de sa ville. Π cs.numero (caserne cs) \ Π cs.numero (σ p.habite=d.addr d.distance<=5 (pompier p caserne cs distance d)) 2.7.2 SQL SELECT caserne.numero FROM caserne EXCEPT SELECT caserne.numero FROM caserne, distance, pompier WHERE pompier.travaille=caserne.numero AND caserne.numero=cas AND pompier.habite=distance.addr AND distance<=5; 2.7.3 Résultat numero -------- 2 3 4 5 6 2.8 requête h Quels sont les pompiers qui habitent dans une ville où il y une caserne à laquelle ils ne sont pas rattachés? 2.8.1 Algèbre relationnel Π numero,nom,travaille,habite ( (pompier adresse ville adresse ac caserne) \ σ pompier.travaille=caserne.numero ( pompier adresse ville adresse ac caserne)) 13
2.8.2 SQL SELECT pompier.* FROM pompier, adresse adrmaison WHERE pompier.habite=adrmaison.numero AND EXISTS ( SELECT * FROM caserne, adresse AS adrc WHERE caserne.siege=adrc.numero AND adrc.ville=adrmaison.ville AND caserne.numero!=pompier.travaille 2.8.3 Résultat numero nom travaille habite --------+----------+-----------+-------- 8 Torvalds 4 4 1 Bennyben 2 5 9 Cox 5 5 4 Toto 1 11 5 Gattes 6 12 6 Dupont 2 14 7 Dupond 3 15 3 Ste 2 17 2.9 requête i Quelles sont les casernes les plus proches de Draguignan? 2.9.1 Algèbre relationnel Selon le sujet, les seules distances que l on possède sont celles concernant les casernes les plus proches d une ville données. On a donc juste à lister ces distances pour notre ville et les casernes en question. Π caserne.numero,distance.distance ( σ ville.nom= Draguignan (ville adresse distance caserne)) 2.9.2 SQL SELECT c.numero, d.distance FROM distance d, caserne c, adresse a, ville v WHERE c.numero=d.cas 14
AND d.addr=a.numero AND a.ville=v.nom AND v.nom= Draguignan ; 2.9.3 Résultat numero distance --------+---------- 1 3 1 30 4 14 4 12 4 12 5 12 5 19 5 2 6 5 6 8 6 10 2.10 requête j Quelles sont les casernes possédant tous les types de camions référencés dans la base? 2.10.1 Algèbre relationnel Π cs.numero ( Π cs.numero,m.nom (casernes cs camion modelecamion m) / Π nom (modelecamion)) 2.10.2 SQL SELECT DISTINCT caserne.numero FROM caserne, camion, modelecamion WHERE camion.stoque=caserne.numero AND camion.modele=modelecamion.nom GROUP BY caserne.numero HAVING count(distinct modelecamion.nom)=(select count(*) FROM modelecamion 2.10.3 Résultat Aucun résultat. 15
2.11 requête k Quelles sont les marques vendant tous les types de camions? 2.11.1 Algèbre relationnel En ayant des types de camions fixes : (Π fabrique (σ type= lourd (modelecamion))) (Π fabrique (σ type= rapide (modelecamion))) 2.11.2 SQL SELECT fabrique FROM modelecamion GROUP BY fabrique HAVING count(distinct type)=( SELECT count(distinct type) FROM modelecamion 2.11.3 Résultat fabrique ---------- Pegot Renault 2.12 requête l Quels sont les camions ayant le maximum de places? 2.12.1 Algèbre relationnel Π numero,places,modele,stoque (camion\ σ c1.places<c2.places (camion c1 camion c2)) 2.12.2 SQL SELECT * FROM camion c WHERE places>=(select MAX(places) FROM camion 16
2.12.3 Résultat numero places modele stoque --------+--------+----------+-------- 11 60 Vroom600 5 17