Sie sind auf Seite 1von 147

Nom : Prénom : page 1

MLBDA – 4I801- Examen réparti du 4 Janvier 2017


Seuls les documents de cours et de TD sont autorisés – Durée : 2h.
Répondre aux questions sur la feuille du sujet dans les cadres appropriés. Utiliser le dos de la feuille précédente si la
réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité de la rédaction sera prise en compte. Ecrire à
l’encre bleue ou noire. Ne pas dégrafer le sujet. Eteindre et ranger tout téléphone et autre appareil électronique.

EX1 EX2 EX3 EX4 Total

Exercice 1. XSchema 4 pts


On considère la DTD suivante représentant une base de personnes :
< !ELEMENT Base(personne )* >
< !ELEMENT personne (nom, prenom, datenais, enfant *)>
< !ATTLIST Personne pseudo ID #REQUIRED
pere IDREF #IMPLIED
mere IDREF #IMPLIED >
<!ELEMENT nom (#PCDATA)>
<!ELEMENT prenom (#PCDATA)>
<!ELEMENT datenais (#PCDATA)>
<!ELEMENT enfant (#PCDATA)>
Chaque personne a un pseudo, utilisé par exemple pour indiquer les enfants d’une personne. Le fragment XML
suivant décrit une personne Pierre et son fils Luc.
<personne pseudo='pierrot'>
<nom >Durand</nom>
<prenom>Pierre</prenom>
<datenais>1970-01-01</datenais>
<enfant>lulu</enfant>
</personne>

<personne pseudo='lulu' pere='pierrot'>


<nom>Durand</nom>
<prenom>Luc</prenom>
<datenais>2000-01-20</datenais>
</personne>

Question 1 (1pt). On souhaite modéliser ces informations en XSchema. Compléter le schéma suivant en
définissant le type PersonType.

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE xs:schema SYSTEM "XMLSchema.dtd">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >

<xs:complexType name=’PersonType’ >


...
...
...
...
...
Lettres initiales du Prénom et du Nom: page 2

<xs:element name='base'>
<xs:complexType>
<xs:sequence maxOccurs='unbounded'>
<xs:element name='personne' type='PersonType' />
</xs:sequence>
</xs:complexType>
</xs:element>

Question 2 (2 pts). Complétez ou modifiez le schéma pour prendre en compte les contraintes suivantes, en
précisant à quel endroit du schéma les ajouts doivent être insérés (ou en réécrivant l’élément que vous
modifiez) :
a) La date de naissance doit être inférieure au 1er janvier 2017.

b) Une personne est identifiée de façon unique par son pseudo.

c) Un enfant est une personne

Question 3 (1pt). On veut pouvoir distinguer dans cette base les personnes majeures. Les personnes majeures
peuvent avoir un conjoint, une profession et un employeur. Le conjoint et l’employeur sont modélisés sous
forme d’éléments, la profession sous forme d’attribut. Définir un type PersMajeureType à partir du type
PersonType décrivant les personnes majeures.
Lettres initiales du Prénom et du Nom: page 3

<xs:complexType name=’PersMajeureType’>
...
...
...
...
...
...
...
...

Exercice 2. XPath 5 pts


On considère l'arbre XML suivant qui modélise un extrait d'un document HTML. Dans cet arbre chaque nœud
est identifié par un attribut @id (l'identifiant de la racine est égal à 0, son élément fils de type p a l'identifiant 1,
etc):

Le résultat d'une expression XPath est une liste de nœuds DOM triés dans l'ordre du document, sans doublon.
Par exemple, l'expression /descendant::div/following-sibling::*/@id retourne les identifiants
6,8,9,11,12.

Question 1 (3 pts). Donnez pour chaque expression XPath la liste des identifiants des nœuds qui sont retournés.
1. /descendant::div[child::*]/@id
Réponse:
Lettres initiales du Prénom et du Nom: page 4

2. /descendant::div/descendant::span/@id
Réponse:

3. /descendant::*/child::*[1]/@id
Réponse:

4. /descendant::*/following-sibling::div[1]/@id
Réponse:

5. /descendant::span[not(following-sibling::*)]/@id
Réponse:

6. /descendant::*[child::div[not(following-sibling::*)]]/@id
Réponse:

Question 2 (2 pts). Donnez pour chaque séquence de nœuds ci-dessous une expression XPath (syntaxe étendue
ou abrégée) qui la calcule:

1. 3, 7, 11
Réponse:

2. 4, 9, 12
Réponse:

3. 4, 6, 11
Réponse:

4. 1, 4
Réponse:
<analyses >
<typesExamens>
<typeExamen num="a01" nom="allergene" seuil="12">
<precaution>a jeun</precaution>
</typeExamen>
<typeExamen num="g01" nom="glycemie" seuil="8"/>
<typeExamen num="p01" nom="plaquettes" seuil="90"/>
</typesExamens>
<patients>
<patient num="19012" nom="smith">
<age>35</age>
<dossier>
<examen>
<quoi>a01</quoi>
<quand>12-12-2014</quand>
<avecQui>7892</avecQui>
<resultat>8</resultat>
</examen>
</dossier>
</patient>
<patient num="6942" nom="ben">
<age>65</age>
<dossier>
<examen>
<quoi>g01</quoi>
<quand>13-11-2014</quand>
<avecQui>5471</avecQui>
<resultat>11</resultat>
</examen>
<examen>
<quoi>p01</quoi>
<quand>14-11-2014</quand>
<avecQui>5471</avecQui>
<resultat>92</resultat>
</examen>
</dossier>
</patient>
</patients>
<personnel>
<praticien num="7892" nom="smith" >
<grade>infirmier</grade>
</praticien>
<praticien num="5471" nom="jade">
<grade>medecein</grade>
</praticien>
</personnel>
</analyses>

analyses.xml
@prefix : <http://dbpedia.org/resource/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

#examens
:allergie
a :examen_medical ;
:nom "allergene" ;
:seuil "12" .
:glycemie
a :examen_medical ;
:nom "glycemie" ;
:seuil "8" .
:plaquettes
a :examen_medical ;
:nom "plaquettes" ;
:seuil "90" .

#patients
:smith
a :patient ;
:nom "smith" ;
:age "35" .
:ben
a :patient ;
:nom "ben" ;
:age "65" .

#praticiens
:salem
a :praticien ;
:grade :infirmier .
:jade
a :praticien ;
:grade :medecin .

#dossiers
:smith :passe :alg .
:alg :quoi :allergie ;
:quand "2015" ;
:parQui :jade .
:ben :passe :glc , :plq .
:glc :quoi :glycemie ;
:quand "2015" ;
:parQui :smith ;
:resultat "6" .
:plq :quoi :plaquette ;
:quand "2012" ;
:parQui :jade ;
:resultat "80" .
analyses.ttl
Nom : Prénom : page 1

MLBDA – 4I801- Examen réparti 2 du 06 janvier 2016


Partie XPath et XQuery

XPath XQuery

XPath et XQuery 10 pts


On considère un extrait d'un site de partage de photos (voir le fichier site.xml donné en
annexe). Le fichier contient des utilisateurs inscrits au site avec un identifiant unique, un nom et
une adresse email. Pour chaque photo du site on connaît l'appareil utilisé, sa catégorie, son format et
sa taille. Les photos sont organisées en collections, chaque collection a un identifiant, elle appartient
à un utilisateur du site, a un nom et contient une liste de photos publiées (élément <publication>),
pour chaque photo de la collection on connaît la date à laquelle elle a été ajoutée à la collection.

XPath 5 pts
Exprimez en XPath les requêtes suivantes (observation: toutes les requêtes demandées peuvent être
exprimées en XPath):

Question 1(1 pt). Les appareils différents de 'Nikon F1' qui ont été utilisés pour prendre les photos
de la collection "Pour les copains".

Résultat:
<appareil> Samsung T1 </appareil>

Question 2(1pt). Les emails des personnes qui n'ont pas de collections avec des photos en format
'gif'.

Résultat:
<email> Pierre.Bernard@acces.fr </email>
<email>Paul.Martin@sept.fr</email>

Question 3(1 pt). La catégorie de la troisième photo publiée (troisième <publication>).


Résultat:
<catégorie>enfants </catégorie>
Nom : Prénom : page 2

Question 4(1pt). Décrire en français le résultat qui sera envoyé par la requête suivante. Donner
également son résultat.
//collection[publication/@date != publication/@date]/nom

Description:

Résultat:

Question 5(1 pt). La liste de tous les formats de photo possibles, chaque format doit être listé une
seule fois.
Résultat:
<format> jpeg</format>
<format> bmp</format>
<format> gif</format>

XQuery 5 pts
Exprimez en Xquery les requêtes suivantes :

Question 6(1pt). Les appareils photo qui ont été utilisés pour faire plusieurs photos. Chaque
appareil doit apparaître une seule fois dans le résultat. Le résultat doit satisfaire la DTD suivante :
< !ELEMENT résultats (appareil)*>
< !ELEMENT appareil EMPTY>
< !ATTLIST appareil nom CDATA>

Question 7(1.5 pt). Pour chaque format de photo, le nombre total de photos de ce format qui ont
été publiées dans chaque collection. Le nombre total sera affiché dans un élément <nb>. S'il n'y a
pas de photo avec un format donné dans une certaine collection, on affiche seulement le nom de la
collection, l'élément <nb> ne sera pas affiché. Chaque format doit apparaître une seule fois dans le
site.xml
<site> <collections>
<photos> <collection idC='c67' idU='m23'>
<photo idP='p123'> <nom> Pour les copains</nom>
<appareil>Samsung T1</appareil> <publication idP='p123' date='17-12-2015'/>
<catégorie>paysage</catégorie> <publication idP='p254' date='18-12-2015'/>
<format> jpeg</format> </collection>
<taille>2056</taille> <collection idC='c78' idU='m56'>
</photo> <nom> Collection publique</nom>
<photo idP='p254'> < publication idP='p678' date='24-12-2015'/>
<appareil>Nikon F1</appareil> </collection>
<catégorie>enfants</catégorie> <collection idC='c34' idU='m62'>
<format> jpeg</format> <nom> Photos préférées</nom>
<taille>1028</taille> < publication idP='p354' date='02-01-2016'/>
</photo> < publication idP='p442' date='02-01-2016'/>
<photo idP='p678'> < publication idP='p553' date='02-01-2016'/>
<appareil>Samsung T1</appareil> </collection>
<catégorie>enfants</catégorie> </collections>
<format> bmp</format> </site>
<taille>1028</taille>
</photo>
<photo idP='p354'>
<appareil>Nikon F1</appareil>
<catégorie>portrait</catégorie>
<format> gif</format>
<taille>512</taille>
</photo>
<photo idP='p442'>
<appareil>Canon D50</appareil>
<catégorie>animaux</catégorie>
<format> gif</format>
<taille>512</taille>
</photo>
<photo idP='p553'>
<appareil>Canon D50</appareil>
<catégorie>nature</catégorie>
<format> gif</format>
<taille>512</taille>
</photo>
</photos>
<utilisateurs>
<utilisateur idU='m23'>
<nom>Bernard</nom>
<prénom> Pierre</prénom>
<email>Pierre.Bernard@acces.fr</email>
</utilisateur>
<utilisateur idU='m56'>
<nom>Martin</nom>
<prénom>Paul</prénom>
<email>Paul.Martin@sept.fr</email>
</utilisateur>
<utilisateur idU='m62'>
<nom>Richard</nom>
<prénom>Thomas</prénom>
<email>Thomas.Richard@aol.fr</email>
</utilisateur>
</utilisateurs>
Nom : Prénom : page 1

MLBDA – 4I801- Examen réparti 2 du 06 janvier 2016


Partie DTD et XSchema, RDF et SPARQL

Ex1 Ex2

Seuls les documents de cours et de TD sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. Le barème est donné à titre indicatif. La qualité de la
rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet. Eteindre et ranger tout téléphone et autre appareil
électronique.

Exercice 1. DTD et XSchema 5 pts


On considère le document analyses.xml fourni en annexe qui décrit les analyses médicales effectuées par des
patients.

Question 1 (1 pt). Complétez la DTD suivante qui définit le document analyse.xml.

< !ELEMENT analyses (…………………………………………………………………………..

< !-- analyses -->


< !ELEMENT …………………………………………………………………………………….

…………………………………………………………………………………………………….

……………………………………………………………………………………………………..

< ! -- typeExamen -- >


< !ELEMENT …………………………………………………………………………………..

…………………………………………………………………………………………………..

………………………………………………………………………………………………….

…………………………………………………………………………………………………..

………………………………………………………………………………………………….

< !-- patient -- >


< !ELEMENT …………………………………………………………………………………..

…………………………………………………………………………………………………..

………………………………………………………………………………………………….

…………………………………………………………………………………………………..
Lettres initiales du Prénom et du Nom: page 2

< -- dossier -->

< !ELEMENT …………………………………………………………………………………..

< !ELEMENT examen (quoi, quand, parQui, resultat) >

< !ELEMENT quoi (#PCDATA)>

< !ELEMENT quand (#PCDATA)>

< !ELEMENT parQui (#PCDATA)>

< !ELEMENT resultat (#PCDATA)>

On souhaite utiliser XSchema à la place des DTD et tirer profit de l’expressivité de XSchema.

Question 2 ( 1 pt).

a- Complétez la définition de l’élément racine du document analyse.xml.

<xs:element …………………………………………>

<…………………………………………>

<…………………………………………>

<xs:element ref='typesExamens'/>

<xs:element ref='patients'/>

<xs:element ref='personnel'/>

</…………………………………………>

</…………………………………………>

</xs:element>

b- Complétez la définition de l’élément typeExamen.

<xs:element ………………………………………..…>

<…………………………………………>
Lettres initiales du Prénom et du Nom: page 3

<…………………………………………>

<………………………………………………………………………………………………/>

</……………………………………….>

<………………………………………………………………………………………………/>

<………………………………………………………………………………………………/>

<………………………………………………………………………………………………/>

</…………………………………………>

</xs:element>

Question 3 (2 pt).
Définir, en XSchema, les contraintes suivantes.
On considère que les contraintes sont exprimées entre les balises <xs:element name='analyses'> et sa
balise fermante </xs :element>

a) Tous les attributs num du document sont uniques pour tout le document.

<……………………………… name="uniqueAllNum">

<………………………………………………………………………………………………/>

<………………………………………………………………………………………………/>

………………………………………………………………………………………………

b) L’attribut num de l’élément examenType est une clé de cet élément.


Rappel : les contraintes sont exprimées entre les balises <xs:element name='analyses'> et sa
balise fermante </xs :element>

<……………………………… name="uniqueExam">

<………………………………………………………………………………………………/>

<………………………………………………………………………………………………/>

………………………………………………………………………………………………
Lettres initiales du Prénom et du Nom: page 4

c) L’attribut num de l’élément praticien est une clé de cet élément.


Rappel : les contraintes sont exprimées entre les balises <xs:element name='analyses'> et sa
balise fermante </xs :element>

<……………………………… name="uniquePrat">

<………………………………………………………………………………………………/>

<………………………………………………………………………………………………/>

………………………………………………………………………………………………

d) Exprimer les contraintes d’intégrité référentielle suivantes :


a. Contrainte refexam de l’élément examen contenu dans patient vers l’élément typeExamen
b. Contrainte refpraticien de l’élément examen contenu dans patient vers l’élément praticien

Rappel : les contraintes sont exprimées entre les balises <xs:element name='analyses'> et sa balise
fermante </xs :element>

a)
<………………………………………………………………………………………………………>

.……………………………….………………………………………………..

.………………………………………………………………………………..

………………………………………………………………………………

b)

<………………………………………………………………………………………………………>

.……………………………….………………………………………………..

..………………………………………………………………………………..

………………………………………………………………………………
Lettres initiales du Prénom et du Nom: page 5

Question 4 (1 pt). On souhaite introduire un type tpersonne pour factoriser les informations communes aux
types patient et praticien. Complétez le fragment du schéma XSchema permettant de réaliser cette factorisation.

<xs:complexType name="tpersonne">

<……………………………… ……………………………… ………………………………/>

<……………………………… ……………………………… ………………………………/>

</xs:complexType>

<xs:complexType name="tpatient">

<xs:complexContent>

<……………………………… ………………………………>

<………………………………>

<xs:element ……………………………… type="xs:string"/>

<xs:element ref="dossier" />

</………………………………>

</………………………………>

</xs:complexContent>

</xs:complexType>

<xs:element name="patient" type="tpatient"/>

<xs:complexType name="tpraticien">

<xs:complexContent>

<………………………………>

<………………………………>

<xs:element ……………………………… ……………………………… />

</………………………………>

</………………………………>

</xs:complexContent>

</xs:complexType>

<xs:element name="praticien" type="tpraticien"/>


Lettres initiales du Prénom et du Nom: page 6

Exercice 2. SPARQL 5 pts


Considérons les triplets du document analyses.ttl donnés sous forme factorisée (cf. annexe)

Question 1 (1 pt). Renseigner les cardinalités (nombre de réponses) des requêtes Q1 à Q3 données ci-dessous.

Q1
select (count(*) as ?nb_triples)
where { ?s ?p ?o }
Résultat : ……..
Q2
select (count(distinct ?p) as ?nb_pred)
where{ ?s ?p ?o }
Résultat : ……..
Q3
select (count(distinct ?o) as ?nb_smth)
where{ ?s rdf :type ?o }
Résultat : ……..

Question 2 (.5 pt). Que retourne la requête Q4 donnée ci-dessous ? Exprimez-la en français et donnez son
résultat dans un tableau.

Q4
select ?pat ?nom
where {
?pat :passe ?ex .
?ex :quoi :glycemie .
?ex :resultat ?res .
:glycemie :seuil ?se .
:glycemie :nom ?nom
FILTER(?res<?se) }

La requête en français :
Lettres initiales du Prénom et du Nom: page 7

Tableau du résultat

Exprimer les requêtes suivantes en SPARQL.

Question 3 (.5 pt). Y a-t-il des patients qui sont également praticiens ?
Le résultat de la requête est : false.

Question 4 (1 pt). Les praticiens qui ont fait passer un examen dont le seuil est strictement inférieur à 12.
Retourner le nom du praticien et le nom de l’examen.
Le résultat de la requête est :
?praticien ?examen
:smith :glycemie

Select ?praticien ?examen

Where

{
Lettres initiales du Prénom et du Nom: page 8

Question 5 (1 pt). Les patients qui ont passé un examen dont on connaît éventuellement le résultat.
Le résultat de la requête est :
?patient ?examen ?resultat
:ben "glycemie" 6
:smith "allergene "

Select ?patient ?examen ?resultat

Where

}
Lettres initiales du Prénom et du Nom: page 9

Question 6 (1 pt). Les praticiens qui ont effectué un examen à deux patients différents.
Remarque : le résultat ne doit pas contenir de doublons.
Le résultat de la requête est
?praticiens ?patient1 ?patient2
:jade « ben » « smith »

Select ?praticiens ?patient1 ?patient2

Where

}
Nom : Prénom : page 1

MLBDA – 4I801- Examen réparti du 2 novembre 2016

Ex1 : Ex2 :

Ex3 : Ex4 :

Seuls les documents de cours et de TD sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. Utiliser le dos de la feuille précédente si la
réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité de la rédaction sera prise en compte. Ecrire à

Exercice 1. Conception objet et objet-relationnel 5 pts


On souhaite modéliser dans le formalisme de l’ODMG une application décrivant des organisations internationales.
Une organisation a un nom, un siège (un nom de ville), un responsable et des pays membres. Chaque pays a un
nom, une capitale, appartient à des organisations, et a un gouvernement composé d’un chef du gouvernement et de
ministres. Un ministre a un nom et un portefeuille.
Question 1. Compléter les interfaces Organisation et Pays du schéma ODL modélisant cette application.
Interface Organisation
{ attribute string nom ;
attribute string siege;

Interface Personne
{ attribute string nom ;
attribute Pays nationalite ;
}

Interface Gouvernement
{attribute Personne chef ;
attribute set(struct(Personne ministre, string portefeuille)) ministres ;
}

Interface Pays
{ attribute string nom ;

Question 2. Quel est le nombre minimum de racines de persistance nécessaires à cette application ? Justifiez
votre réponse et définissez ces racines.
Nb minimal de racines de persistance :

Justification :
Lettres initiales du Prénom et du Nom: page 2

Définition des racines de persistance (précisez où elles doivent apparaître


dans le schéma):

Question 3. Dans l’application, un traitement particulier s’applique aux pays de la zone Euro. Pour cela, on a
besoin de connaître le PIB de ces pays. Complétez le schéma précédent en conséquence.

Question 4. On veut définir le schéma de l’application décrite dans la question 1 en SQL3.


En supposant que les types Organisation et Personne sont déjà définis, complétez le schéma en
ajoutant la définition du type Pays :

Create type _ _ _ _ _ _

Create type Pays as object (

Nom varchar2(20),

Capitale varchar2(20),

Gouv _ _ _ _ _ _ _ _ _ _

Appartient _ _ _ _ _ _ _ _ _

) ;
Lettres initiales du Prénom et du Nom: page 3

Question 4. Définissez la table LesPays permettant de stocker l’ensemble des pays.

Exercice 2. XML DTD Xschema 2 pts


Soit la DTD suivante :

< !ELEMENT A ( (D | (B,C+) ?)+ , ((B? | (C,D))+, B)* )>


< !ELEMENT B EMPTY>
< !ELEMENT C EMPTY>
< !ELEMENT D EMPTY>

Question 1. Les éléments suivants sont-ils conformes à la DTD ?


a) <A> <D/> <B/> <C/> <D/> <B/> <B/> <D/> </A>

Conforme : OUI NON (entourer la bonne réponse)


Si NON, pourquoi ?

b) <A> <B/> <C/> <B/> <C/> <D/> <B/> <C/><B/> </A>

Conforme : OUI NON (entourer la bonne réponse)


Si NON, pourquoi ?

c) <A> <D/> <B/> <C/> <C/> <B/> <B/> <B/> <B/> </A>
Conforme : OUI NON
Si NON, pourquoi ?

Question 2. Les deux définitions suivantes sont-elles équivalentes ?


< !ELEMENT A (B|C)*> et < !ELEMENT A (B ?, C ?) * >
Lettres initiales du Prénom et du Nom: page 4

Exercice 3. XSchema 2 pts

Question 1 : Les affirmations suivantes sont-elles exactes ? Justifier.

a) L’élément <elt att=‘1’ /> est de type simple (i.e. simpleType).

VRAI FAUX (entourez la bonne réponse)


Pourquoi ?

b) Il est impossible de restreindre un type complexe avec une facette. Est-ce exact ?

OUI NON (entourez la bonne réponse)


Pourquoi ?

Question 2 : Soit la définition suivante :

<xs:simpleType name="S"> <xs:complexType name="A">


<xs:restriction base="xs:string"> <xs:simpleContent>
<xs:enumeration value="a"/> <xs:extension base="xs:string">
<xs:enumeration value="b"/> <xs:attribute name="x" type="S"
<xs:enumeration value="c"/> use="required"/>
</xs:restriction> </xs:extension>
</xs:simpleType> </xs:simpleContent>
</xs:complexType>

<xs:element name="E" type="A"/>

Donnez un exemple d’élément XML nommé E conforme à cette définition.


Lettres initiales du Prénom et du Nom: page 5

Exercice 4. SQL3 : requêtes et méthodes 11 pts


On considère le schéma SQL3 suivant décrivant des auteurs spécialisés dans plusieurs domaines et écrivant des
documents. Un document a plusieurs mots-clés et peut être écrit par plusieurs auteurs. Un nom de domaine peut
correspondre à un mot-clé.
create type Auteur; create type Auteur as object(
/
create type Document; prenom varchar2(30),
/ domaines EnsMots,
create type EnsMots as table of varchar2(30); ecrit EnsDoc,
/ member function nbDoc(a Number) return Number,
create type EnsDoc as table of REF Document; member function coauteurs return EnsAuteurs,
/ member function domainesDistants(d Number)
create type EnsAuteurs as table of REF Auteur; return EnsMots
/ );
create type Document as object ( /
annee number(4),
nbpages number(3),
titre varchar2(30),
motscles EnsMots,
auteurs EnsAuteurs
);
/

Stockage :
Les objets Document sont stockés dans la table LesDoc.
Les objets Auteur sont stockés dans la table LesAuteurs.
Répondre en SQL3, en suivant le modèle du cadre réponse.
1) Insertion
On suppose que les deux instructions suivantes ont été effectuées sur la base :
Insert into LesAuteurs values (‘Alice’, EnsMots(‘info’, ‘données’), EnsDoc()) ;
Insert into LesDoc values (‘2016, 100, ‘Les BD’, EnsMots(‘BD’, ‘langage’),
EnsAuteurs()) ;
Ecrivez l’instruction SQL3 qui insère l’auteur Alice dans les auteurs du document de titre ‘Les BD’ ;

Insert _ _ _ _ _ _ _ _ _ _

2) Interrogation : formuler les requêtes suivantes.


a) Quels sont les auteurs ayant écrit en 2010 au moins un document de plus de 20 pages ? Le résultat affiche des
objets Auteur. Le résultat ne contient pas de doubles.
Lettres initiales du Prénom et du Nom: page 6

Select _ _ _ _ _ _ _ _

From _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

b). Quels sont les auteurs ayant écrit au moins un document dont au moins un mot-clé est égal à un domaine de
l'auteur ? Afficher le prénom de l'auteur, le titre du document et le mot-clé correspondant au domaine de
l'auteur.

Select _ _ _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _

c).Quelles sont les paires de documents qui ont au moins 3 mots-clés en commun. Afficher les références des
deux documents et le nombre de mots-clés communs.

Select ref(d1), ref(d2), _ _ _ _ _ _ _ _

From LesDoc d1 ; LesDoc d2, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _

d) Qu’affiche la requête suivante?


select distinct value(m)
from LesDoc d, table(d.motscles) m
where d.annee = 2016
and value(m) not in (select value(m1)
from LesDoc d1, table(d.motscles) m1
where d1.annee = 2015);
Lettres initiales du Prénom et du Nom: page 7

e) Quels sont les co-auteurs d'Alice en 2015. Afficher des objets Auteur. Rmq. : un co-auteur d’Alice est
l’auteur d’un document écrit par Alice. Alice n’est pas son propre coauteur. Répondre SANS utiliser la méthode
coauteurs().

Select _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _

_ _ _ _ _ _ _ _ _

3) Méthodes
3a) En invoquant la méthode nbDoc(a) du type Auteur. Pour chaque auteur ayant écrit plus de documents en
2015 qu'en 2014, donner son prénom et le nombre de documents écrits en 2015.

Select _ _ _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

3b) En invoquant la méthode coauteurs() du type Auteur : parmi les coauteurs d'Alice afficher ceux qui ont le
domaine 'Musique'?

Select _ _ _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

3c) Ecrire la méthode coauteurs. On rappelle qu’un auteur n’est pas son propre coauteur.

member function coauteurs return EnsAuteurs is


res _ _ _ _ _ _ _ _;
begin
_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

return res;
end;
end;
Lettres initiales du Prénom et du Nom: page 8

4) Récursion. On considère la méthode récursive domainesDistants(d number) du type Auteur qui retourne un
ensemble de mots (type EnsMots). Elle est définie comme suit :
• domainesDistants(1) retourne les domaines d’un auteur.
• domainesDistants(2) retourne l’union des domaines d’un auteur et des domaines de ses coauteurs.
Autrement dit, cela retourne l’union des domaines d’un auteur et des domainesDistants(1) de ses coauteurs
etc.
• domainesDistants(d) retourne l’union des domaines d’un auteur et des domainesDistants(d-1) de ses
coauteurs.
Ecrire le corps de la méthode récursive

member function domainesDistants(d Number) return EnsMots is

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _
Nom : Prénom : page 1

MLBDA – 4I801- Examen 2ème session du 10 juin 2015


Ex1 Ex2 Ex3 Ex4 Ex5 Total

Seuls les documents de cours et de TD sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. Utiliser le dos de la feuille précédente si la réponse déborde
du cadre. Le barème est donné à titre indicatif. La qualité de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas
dégrafer le sujet. Eteindre et ranger tout téléphone et autre appareil électronique.

Exercice 1. SQL3 5 pts


On considère le schéma SQL3 suivant décrivant des jeux de tirage (loto, euro million, ...). Lire la 1ère colonne
puis la 2ème.

create type Cases as table of Number(2); create type Joueur as object (


/ prenom Varchar2(30), // le prénom est unique
create type Ticket as object ( achat Tickets
jeu Varchar2(30), );
combinaison Cases, /
jour Date, // la date du ticket ex. ’13-6-2014’ // Club sportif
prix Number // le prix de vente create type Club as object (
); nom Varchar2(30),
/ ville Varchar2(30),
create type Tickets as table of Ticket; president ref Joueur
/ ) not final;
/
create table LesJoueurs of Joueur …;
create table LesClubs of Club;
1) On suppose que la table LesJoueurs contient déjà le joueur Alan qui a joué au loto le vendredi 13-12-2013 la
combinaison (1,3,5,7,9) pour 2 euros, et le vendredi 13-6-2014 la combinaison (2,4,6,8,10) pour 12 euros.
a) Insérer le club AP6 de Paris présidé par Alan.

INSERT INTO _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

b) On apprend que le prix du ticket de loto joué par Alan le 13-12-2013 ne valait pas 2 euros mais 20 euros.
Modifier la base en conséquence. Ecrire la modification en SQL3.

UPDATE _ _ _ _ _ ( _ _ _ _ _ _ _ _

_ _ _ _ _ _ _

_ _ _ _ _ _ _ )
Lettres initiales du Prénom et du Nom: page 2

SET _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

WHERE _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _

2) On suppose que la base contient plusieurs joueurs. Qu’affiche cette requête ? Répondre en une phrase brève.
select value(j)
from LesJoueurs j
where ( select count(value(a))
from table(j.achat) a) = ( select max(( select count(value(a2))
from table(j2.achat) a2))
from LesJoueurs j2)
;

Elle affiche _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
_ _ _

3) Ecrire la requête : pour un président ayant acheté au moins un ticket le 27-10-2014, donner son prenom et le
nom du club qu’il préside. Trier le résultat par nom de club.

Select _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _

4) Pour chaque président de club, afficher le président (i.e. afficher entièrement l’objet de type Joueur) et le
nombre de clubs qu'il préside.

Select _ _ _ _ _ _ _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _

5) On complète le type Joueur avec la méthode numFavorisAuLoto() retournant les numéros que le joueur a
déjà joués au moins 5 fois au loto. Compléter le corps de cette méthode

member function numFavorisAuLoto return Cases is

resultat _ _ _ _ _ _
begin
Lettres initiales du Prénom et du Nom: page 3

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _

return resultat ;
end ;

6) (bonus) Afficher le prénom des joueurs qui ont 13 parmi leurs numéros favoris au loto. Répondre en
invoquant une méthode.

Select _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _

Exercice 2. XML-DTD-XSchema 4 pts


On souhaite écrire une DTD pour le fichier tweets.xml (annexe 2) qui décrit les messages envoyés sur le site
web de Twitter.
Question 1 (1 pt). Complétez la DTD ci-dessous :

< !ELEMENT tweets ……………

< !ELEMENT tweet …………….

< !ELEMENT retweetDe………………..

<!ELEMENT date (#PCDATA)>


<!ELEMENT auteur EMPTY>
<!ATTLIST auteur id ID #REQUIRED>
<!ELEMENT hashtags (hashtag)+>
< !ELEMENT hashtag (#PCDATA)>
Lettres initiales du Prénom et du Nom: page 4

Question 2 (1,5 pt). On souhaite définir un schema XSchema pour modéliser les informations du fichier
tweets.xml. Complétez la définition de l’élément tweet ci-dessous, afin qu’il soit conforme au fichier
tweets.xml.

<xs:element name="tweets">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element ref="tweet"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="tweet">
<xs:complexType>
…………………
………………….
<xs:element name="date" type="xs:string"/>
<xs:element name="auteur" ……………
…………………………………………………..
…………………………………………………..
…………………………………………………
…………………………………………………..

</xs:element>
<xs:element name="texte" type="xs:string"/>
<xs:element name="hashtags" …………………
…………………………………………………………..
………………………………………………………….
………………………………………………………….
. ………………………………………………………….
………………………………………………………….

</xs:element>
<xs:element name="retweetDe"……………….
……………………………………………………………..
…………………………………………………………….
……………………………………………………………
………………………………………………………………

</xs:element>
Lettres initiales du Prénom et du Nom: page 5

……………………………………………………………
……………………………………………………………
…………………………………………………………….
<xs:attribute name="id" type="xs:string" …………………….
<xs:attribute name="langue" type="xs:string" ………………….
<xs:attribute name="type" type="xs:string"………………………
……………………………………………………………..
…………………………………………………………….
…………………………………………………………….
</xs:complexType>
</xs:element>
</xs :schema>

Question 3 (1,5 pts).


Définir les contraintes suivantes en indiquant où les modifications doivent être effectuées :

a) L’attribut id de l’élément tweet est une clef pour cet élément.

b) L’attribut tw de l’élément retweetDe doit référencer un tweet existant dans la base.

c) La longueur d’un tweet est limitée à 140 caractères.


Lettres initiales du Prénom et du Nom: page 6

Exercice 3. XPath 3 pts


On considère le fichier "tweets.xml" (annexe 2) qui décrit les messages (tweets) envoyés sur le site web de
microblogage Twitter. Exprimez en XPath les requêtes suivantes :
Question 1 (0,5pt). Le texte des tweets avec le hashtag "Nepal" ou "Katmandou".

Question 2 (0,5pt). L'identifiant des tweets sans hashtags.

Question 3 (0,5pt). Le deuxième hashtag des tweets écrits en français, s'il y en a.

Question 4 (0,5pt). Le tweet qui suit dans le document le tweet avec l'identifiant "t2".

Question 5 (1pt). Donnez le résultat des requêtes XPath suivantes :


a) //tweet[@langue="fr"][3]/@id
Résultat :

b) //tweet[3][@langue="fr"]/@id
Résultat :

Exercice 4. XQuery 4 pts


On considère les fichiers "tweets.xml" (annexe 2) et " utilisateurs.xml" (annexe 3) contenant la liste des
utilisateurs de Twitter.
Exprimez en XQuery les requêtes suivantes. Pour chaque requête, on donne la DTD du résultat qu’on veut
obtenir et un exemple de résultat en XML.

Question 1 (1 pt). Le login et nom des utilisateurs avec au moins 2 tweets :

DTD du résultat : Exemple


<!ELEMENT resultat (utilisateur)*> <resultat>
<!ELEMENT utilisateur EMPTY> <utilisateur login="@afpfr"
<!ATTLIST utilisateur login CDATA> nom="Agence France-Presse"/>
<!ATTLIST utilisateur nom CDATA> <utilisateur login="@pauwels"
nom="Chloé Pauwels"/>
</resultat>
Annexe 1 : Données SPARQL

@prefix : <http://dbpedia.org/resource/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

#actors
:ryan_gosling
a foaf:actor ;
rdfs:label "Ryan Gosling";
:birthDate "1980-11-12" ;
:countryOfBirth "Canada" .

:Christina_Hendricks
a foaf:actor ;
rdfs:label "Christina Hendricks" ;
:birthDate "1975-05-03" .

:Carey_Mulligan
a foaf:actor ;
rdfs:label "Carey_Mulligan" ;
:birthDate "1985-05-28" ;
:countryOfBirth "UK".

#movies

:drive
a :movie;
:budget "12";
:year "2012";
:rating "7.8";
:seen "352000".

:madmen
a :movie;
:budget "8";
:year "2007";
:rating "7.2";
:seen "96000".

:gangster_squad
a :movie;
:budget "15";
:year "2013";
:rating "6.8";
:seen "160000".

#plays
:ryan_gosling
:plays :drive , :gangster_squad .

:Christina_Hendricks
:plays :drive , :madmen .

:Christina_Hendricks
:plays :gangster_squad , :never_let .
Annexe 2. Fichier tweets.xml

<tweets>
<tweet id="t1" langue="fr">
<date>144401235000</date>
<auteur id="u2" />
<texte>L'application #AppleStore débarque en #Belgique http://bit.ly/1R8VR6t</texte>
<hashtags>
<hashtag>AppleStore</hashtag>
<hashtag>Belgique</hashtag>
</hashtags>
</tweet>
<tweet id="t2" langue="en">
<date>144401245000</date>
<auteur id="u2" />
<texte>Vote for #Belgique! #Eurovision</texte>
<hashtags>
<hashtag>Belgique</hashtag>
<hashtag>Eurovision</hashtag>
</hashtags>
</tweet>
<tweet id="t3" langue="fr">
<date>144401245200</date>
<auteur id="u3" />
<texte>L'histoire du Juge Renaud en BD : fb.me/2fdfCekLM</texte>
</tweet>
<tweet id="t4" langue="fr">
<date>144401249000</date>
<auteur id="u1" />
<texte>#Haiti fait un don symbolique au #Nepal</texte>
<hashtags>
<hashtag>Nepal</hashtag>
<hashtag>Haiti</hashtag>
</hashtags>
</tweet>
<tweet id="t5" langue="fr">
<date>144401262000</date>
<auteur id="u1" />
<texte>Notre mission à #Katmandou suite au séisme : bit.ly/p5ssJj</texte>
<hashtags>
<hashtag>Katmandou</hashtag>
</hashtags>
</tweet>
<tweet id="t5" langue="fr" type="retweet">
<date>144401285000</date>
<auteur id="u2" />
<retweetDe tw="t5" />
<texte>RT Notre mission à #Katmandou suite au séisme : bit.ly/p5ssJj</texte>
<hashtags>
<hashtag>Katmandou</hashtag>
</hashtags>
</tweet>
</tweets>
Annexe 3. Fichier utilisateurs.xml

<utilisateurs>
<utilisateur id="u1">
<pays>France</pays>
<login>@afpfr</login>
<nom>Agence France-Presse</nom>
<abonnés>943000</abonnés>
</utilisateur>

<utilisateur id="u2">
<pays>Belgique</pays>
<login>@pauwels</login>
<nom>Chloé Pauwels</nom>
<abonnés>212</abonnés>
</utilisateur>

<utilisateur id="u3">
<pays>États-Unis</pays>
<login>@dupont</login>
<nom>Rémy Dupont</nom>
<abonnés>120</abonnés>
</utilisateur>

<utilisateur id="u4">
<pays>Belgique</pays>
<login>@pauwels</login>
<nom>Laura Peeters</nom>
<abonnés>432</abonnés>
</utilisateur>
</utilisateurs>
Nom : Prénom : page 1

MLBDA – 4I801- Examen réparti du 7 janvier 2015


Version CORRIGEE

Ex1 Ex2 Ex3 Ex4 Ex5 Total

Seuls les documents de cours et de TD sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. Utiliser le dos de la feuille précédente si la réponse déborde
du cadre. Le barème est donné à titre indicatif. La qualité de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas
dégrafer le sujet. Eteindre et ranger tout téléphone et autre appareil électronique.

Exercice 1. Xschema 5 pts


On considère le fichier formation.xml (annexe 1) décrivant l’emploi du temps d’une formation universitaire. On
souhaite définir le schéma XML validant ce fichier en complétant le fichier formation.xsd (annexe 2).

Question 1 (1 pt). Complétez la définition de l’élément semestre (voir annexe 1), sachant que le contenu
d’un élément semestre est de la forme Si avec i ∈ {1, 2}.
<xs:element name="semestre">

</ xs:element>

<xs:element name="semestre">
<xs:simpleType>
<xs:restriction base ="xs :string">
<xs :pattern value = "S1 | S2 "/>
</xs :restriction>
</xs :simpleType>
</ xs:element>
On peut aussi mettre pattern value = "S[1-2]" ou enumeration value ="S1" (2 éléments enumeration pour les 2 valeurs)

Question 2 (1 pt). Complétez la définition de l’élément creneau du fichier formation.xsd (voir annexe 1)
sachant qu’un créneau est caractérisé par les informations suivantes :
- Le moment où a lieu le créneau (élément semestre ou élément le)
- Le jour de la semaine du créneau
- L’heure du début et de fin du créneau (éléments de et a)
- La salle
- Un ou deux intervenants
- Une matière

<xs:element name="creneau">
Lettres initiales du Prénom et du Nom: page 2

</ xs:element>
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:element name="le" type="xs:date"/>
<xs:element ref="frm:semestre"/>
</ xs:choice>
<xs:element name="jour" type="frm:jour−de−la−semaine"/>
<xs:element name="de" type="xs:time"/> ** string est aussi accepté
<xs:element name="a" type="xs:time"/> **ici aussi
<xs:element name="salle" type="xs:string" />
<xs:element name="intervenant" type="xs:string" maxOccurs="2" />
<xs:element name="matiere" type="xs:string"/>
</ xs:sequence>
</xs:complexType>

Question 3 (1 pt). Expliquez pourquoi ce schéma n’aurait pas pu être décrit par une DTD (donnez une raison
autre que l’utilisation de types).

Ce fichier contient deux éléments matière (un élément matière dans créneau et un élément matiere dans matieres) qui ne
sont pas du même type.

Question 4 (2 pts). On souhaite préciser la contrainte suivante : tout créneau doit se référer à une matière qui
existe. Définissez cette contrainte en précisant à quels endroits vous ajoutez les déclarations nécessaires.

Dans la definition de l’élément matieres (à la fin, entre </xs:complexType> et </xs:element>

<xs:key name="cleMatiere">
<xs:selector xpath="frm:matiere"/>
<xs:field xpath="frm:sigle"/>
</ xs:key>
Lettres initiales du Prénom et du Nom: page 3

Dans la définition de l’élément formation entre </xs:complexType> et </xs:element>

<xs:keyref name="referenceMatiere" refer="frm:cleMatiere">


<xs:selector xpath="frm:creneaux/frm:creneau"/>
<xs:field xpath="frm:matiere"/>
</ xs:keyref>

Exercice 2. XPath 4 pts


On considère le fichier "sports.xml" (annexe 3) qui décrit les épreuves des sports des jeux olympiques d’hiver
2014. Exprimez en XPath les requêtes suivantes :
Question 1 (0,5pt). Le nom des sports qui n'ont eu aucune épreuve le "23-02".

//sport[not(epreuve[date='23-02'])]/@nom

Question 2 (0,5pt). Le type de la 3e épreuve de chaque sport (s’il y en a).

//sport/epreuve[3]/@type

Question 3 (1pt). Les noms des sports avec au moins 2 épreuves pour les hommes ou 2 pour les femmes.

//sport[count(epreuve[@category="Femmes"]) > 1 or
count(epreuve[@category="Hommes"]) > 1 ]/@nom
Question 4 (1pt). Le type des épreuves en 'Ski de fond' qui précèdent les '50 km libre' dans le document.

//sport[@nom="Ski de fond"]/epreuve[@type="50km libre"]/preceding-sibling::*/@type

Question 5 (1pt). Expliquez en une phrase en français ce que renvoie la requête XPath suivante :
//sport/epreuve/date[. = preceding::date]

Les dates où il y a eu au moins deux épreuves


Pour éviter les doublons, il faudrait écrire :
Lettres initiales du Prénom et du Nom: page 4

//sport/epreuve/date[. = preceding::date and not(. = following::date)]

Exercice 3. XQuery 6 pts


On considère les fichiers "sports.xml" (annexe 3) et " gagnants.xml" (annexe 4) contenant la liste des gagnants
de médailles. Ce fichier contient uniquement les athlètes ayant gagné une médaille au moins.
Exprimez en XQuery les requêtes suivantes. Pour chaque requête, on donne la DTD du résultat qu’on veut
obtenir et un exemple de résultat en XML.

Question 1 (1,5 pt). Le nombre d'athlètes par pays :

DTD du résultat : Exemple


<!ELEMENT resultat (pays)+> <resultat>
<!ELEMENT pays EMPTY> <pays nom="Pays-Bas" nb="4"/>
<!ATTLIST pays nom CDATA> <pays nom="Corée du Sud" nb="1"/>
<!ATTLIST pays nb CDATA> ...
</resultat>

<resultat> {

} </resultat>

for $pays in distinct-values(doc("athletes.xml")//pays/text())


let $ath := doc("athletes.xml")//athlete[pays/text()=$pays]/@id
let $nbr := count($ath)
return <pays nom="{$pays}" medailles="{$nbr}">
Question 2 (1,5 pt). Le(s) plus jeune(s) athlète(s) par pays :

DTD du résultat Exemple


<!ELEMENT resultat (pays)+> <resultat>
<!ELEMENT pays (jeune)+> <pays nom="Pays-Bas" age-min="27">
<!ATTLIST pays nom CDATA> <jeune nom="Smeekens" prenom="Jan"/>
<!ATTLIST pays age-min CDATA> <jeune nom="Stoch" prenom="Kamil"/>
<!ELEMENT jeune EMPTY> </pays>
<!ATTLIST jeune nom CDATA> <pays nom="Norvège" age-min="23">
<!ATTLIST jeune prenom CDATA> <jeune nom="Weng" prenom="Heidi"/>
</pays>
...
</resultat>

<resultat> {
for …
Lettres initiales du Prénom et du Nom: page 6

doc("athletes.xml")//athlete[nom/text()="Stoch" and
prenom/text()="Kamil"]/@id]/date,
$e in doc("sports.xml")//sport/epreuve[date/text()=$d/text()]/@type
return <epreuve type="{$e}" date="{$d}" />

Question 4 (1,5 pt). Les athlètes compatriotes du gagnant (médaille d'or) de l'épreuve "50 km libre" du "Ski de
fond" :

DTD du résultat Exemple


<!ELEMENT resultat (athlete)*> <resultat>
<!ELEMENT athlete EMPTY> <athlete nom="Fatkulina" prenom="Olga"/>
<!ATTLIST athlete nom CDATA> </resultat>
<!ATTLIST athlete prenom CDATA>

<resultat> {

} </resultat>

for $gagnant in doc("sports.xml")//sport[@nom="Ski de fond"]


/epreuve[@type="Sprint"]/medaille-or/@aid
for $pays in doc("athletes.xml")//athlete[@id=$gagnant]/pays/text()
for $a in doc("athletes.xml")//athlete[pays/text()=$pays and @id!=$gagnant]
return <athlete nom="{$a/nom/text()}" prenom="{$a/prenom/text()}" />

Exercice 4. SPARQL 4 pts

Considérons les triplets suivants donnés sous forme factorisée :


Lettres initiales du Prénom et du Nom: page 7

@prefix : <http://dbpedia.org/resource/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

#singers
:Shania_Twain
a foaf:Singer ;
rdfs:label "Shania Twain"@en ;
:birthDate "1965-08-28" ;
:placeOfBirth "Windsor"@en ;
:genre :country_pop , :country_rock , :rock , :pop ;
:instruments "vocals" , :guitar .
:Whitney_Houston
a foaf:Singer ;
rdfs:label "Whitney Houston"@en ;
:birthDate "1963-08-09" ;
:placeOfBirth "Newark"@en ;
:deathDate "2012-02-11" ;
:genre :pop , :sould, :rnb ;
:instruments "vocals" , :piano .
:Mariah_Carey
a foaf:Singer ;
rdfs:label "Mariah Carey"@en ;
:birthDate "1969-03-27";
:placeOfBirth "Long Island"@en ;
:genre :pop , :soul, :rnb ;
:instruments "vocals" , :guitar .
:Jay-Z
a foaf:Singer ;
rdfs:label "Jay-Z"@en ;
:birthDate "1969-12-04" ;
:placeOfBirth "Brooklyn"@en ;
:genre :hiphop ;
:instruments "vocals" .

#actors
:Emilia_Clarke
a foaf:Actor ;
rdfs:label "Emilia Clarke"@en ;
:birthDate "1987-05-01";
:placeOfBirth "London"@en ;

#songs
:Emilia_Clarke
:sang :fisherman .
:Whitney_Houston
:sang :believe , :run .
:Mariah_Carey
:sang :believe , :odds, :myall .
:Shania_Twain
:sang :kaching .
:Jay-Z
:sang :empire .
Lettres initiales du Prénom et du Nom: page 8

Exprimer les requêtes suivantes en SPARQL.


Remarque : ne pas écrire la déclaration des préfixes dans les requêtes

Question 1 (1 pt). Les chanteurs de pop et de rock qui jouent de la guitare.


Le résultat de la requête est
singer
:Shania_Twain

prefix : <http://dbpedia.org/resource/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix foaf: <http://xmlns.com/foaf/0.1/>
# les chanteurs de pop et de rock qui jouent de la guitare.
select ?singer
{
?singer :genre :pop . ?singer :instruments :guitar . ?singer :genre
:rock .
}

Question 2 (1 pt). Les duos des chanteurs ayant chanté ensemble. (Une réponse sans doublon donne un bonus)
Le résultat de la requête est :
singer other
:Mariah_Carey :Whitney_Houston

select ?singer ?other


{
?singer a foaf:Singer . ?singer :sang ?song . ?other :sang ?song
Filter (?other!=?singer && str(?other) >str(?singer))
}

Question 3 (1 pt). Les chanteurs en vie ayant réalisé un duo avec des chanteurs qui sont décédés. Retourner le
nom du chanteur en vie et de celui décédé.
Lettres initiales du Prénom et du Nom: page 9

Le résultat de la requête est :


singer collab
:Mariah_Carey :Whitney_Houston

select ?singer ?collab


{
?singer a foaf:Singer . ?collab a foaf:Singer. ?collab :deathDate ?dc.
?singer :sang ?s . ?collab :sang ?s
OPTIONAL {?singer :deathDate ?ds} Filter (!bound(?ds))
}
Question 4 (1,5 pt). Le chanteur qui chante le plus grand nombre de chansons avec le nombre de ces
chansons. (on suppose que le nombre total de chansons est différent pour chacun).
Le résultat de la requête est
singer total-songs
:Mariah_Carey 3

select ?singer (count(?song) as ?total_songs)


{
?singer a foaf:Singer . ?singer :sang ?song
}
group by ?singer
order by DESC(?total_songs )
limit 1
Exercice 5. Intégration de données 1 pt
Il existe deux grands types d’architecture pour l’intégration de données : les entrepôts de données où les
données intégrées sont matérialisées et les médiateurs, où l’intégration est virtuelle. Expliquez pourquoi les
entrepôts de données sont mieux adaptés que les médiateurs pour les applications de type OLAP (applications
d’aide à la décision).
Lettres initiales du Prénom et du Nom: page 10

Les requêtes OLAP utilisent de très grandes quantités de données, font des opérations coûteuses (group by,
agrégats), et ont besoin d’utiliser des données historisées.
L’utilisation d’un entrepôt permet d’optimiser les requêtes en mettant des index, en créant des résumés de
données et en stockant les historiques. Cela permet aussi de ne pas dégrader les performances des BD
opérationnelles.
Le médiateur a de très mauvaises performances, surtout pour les requêtes utilisant de grandes quantités de
données.
Nom : Prénom : page 1

MLBDA – 4I801- Examen réparti du 5 novembre 2014


Version CORRIGEE

Ex1 :

Ex2 :

Ex3 :

Seuls les documents de cours et de TD sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. Utiliser le dos de la feuille précédente si la
réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité de la rédaction sera prise en compte. Ecrire à
l’encre bleue ou noire. Ne pas dégrafer le sujet. Eteindre et ranger tout téléphone et autre appareil électronique.

Exercice 1. OQL 7 pts


On considère le schéma ODL suivant décrivant le contenu du musée du Louvre.

Interface Artiste {keys id ; extent LesArtistes ;


Attribute long id ;
Attribute string nom ;
Relationship set<Œuvre> oeuvres inverse Œuvre :: realiséPar ;
};
Interface Œuvre { extent LesOeuvres ;
Attribute string nom ;
Attribute integer annee ;
Relationship Artiste realiséPar inverse Artiste :: œuvres ;
Relationship Salle estDans inverse Salle :: contient
Relationship set<Document> description ;
};
Interface Sculpture : Œuvre {
Attribute string matière ; -- marbre, bois, ..
Attribute long hauteur;
};
Interface Peinture : Œuvre {
Attribute string technique ; -- huile sur toile, aquarelle, …
};
Interface Salle {
Attribute integer numero ;
Attribute integer étage ;
Attribute string collection;
Relationship set<Oeuvre> contient inverse Oeuvre :: estDans;
};
Interface Document {
Attribute string auteur ;
Attribute string titre ;
Attribute integer annee ;
};
Question 1. Racines de persistance
Peut-on stocker toutes les instances de la base avec la racine de persistance LesArtistes ? Justifiez votre réponse.

Entourer : OUI NON Justifier : .....

Si oui, pourquoi a-t-on défini la racine LesOeuvres ? Justifiez votre réponse à l’aide d’un exemple.
Lettres initiales du Prénom et du Nom: page 2

Si non, est-il possible de stocker toutes les instances de la base avec une seule racine de persistance autre que
LesArtistes ? Préciser de quelle racine il s’agit et justifier votre réponse.

1pt ;
Oui, grâce aux associations œuvres, estDans, description.
Pour simplifier l’expression de requêtes, par exemple celles qui ne mentionnent pas les artistes (ex : titre des
œuvres exposées dans la salle 3 du 1er étage.) On ne pourrait pas non plus avoir des salles sans œuvre.
Oui, LesOeuvres, grâce à l’association realiséPar qui donne accès aux artistes et lesSalles, avec l’association
Contient qui donne accès aux œuvres (puis au reste).

Question 2. L’association entre Œuvre et Salle est déclarée comme étant inverse. Il est possible de déclarer
cette association sans inverse, de la façon suivante :
Interface Œuvre {…. Relationship Salle estDans ; …}
Interface Salle { …. Relationship Set<Œuvre> contient ;}
a) Quel est l’intérêt de déclarer cette association avec inverse ?

0,5pt
permet de contrôler l’intégrité référentielle (une œuvre est dans une salle que si l’œuvre existe, et la salle
contient une œuvre que si elle existe). Permet de garantir la cohérence : l’œuvre X est dans la salle Y, la salle Y
contient l’œuvre X).
b) Peut-on écrire le même ensemble de requêtes sur la base dans les deux cas ?

0,5pt Oui

Question 3. Ecrivez en OQL les requêtes suivantes :


a) Quelles sont les œuvres de Leonard de Vinci ?

0,5pt
Select o
From o in lesOeuvres
Where o.realiséPar.nom = ‘Leonard de Vinci’;
Lettres initiales du Prénom et du Nom: page 3

b) Liste des auteurs ayant écrit un ouvrage sur la ‘Joconde’

0,5pt
Select d.auteur
From o in LesOeuvres, d in o.description
Where o.nom=’Joconde’;
c) Liste des salles présentant les œuvres de la collection ‘peinture italienne’ triées par étage et par numéro
(sans doublon).

1pt
Select distinct o.estDans
From o in LesOeuvres
Where o.estDans.collection=’peinture italienne’
Order by o.estDans.etage, o.estDans.numero

d) Utilisez la question précédente pour lister les œuvres de la collection ‘peinture italienne’ classées par
étage et numéro de salle. Le résultat est un triplet (étage, salle, œuvres)
Lettres initiales du Prénom et du Nom: page 4

1pt
Select struct (etage : o.estDans.etage,
Salle : o.estDans.num,
Œuvres : (select c from c.in s.contient)
)
From s in ( Select distinct o.estDans
From o in LesOeuvres
Where o.estDans.collection=’peinture italienne’
Order by o.estDans.etage, o.estDans.numero);

Question 4.
a) Ecrire une méthode sculpt() permettant de distinguer le type d’une œuvre (sculpture ou peinture). sculpt ()
retourne true s’il s’agit d’une sculpture, false s’il s’agit d’une peinture.

1pt
boolean Œuvre :: sculpt() {return()} ;
boolean Sculpture ::sculpt() {return true};
boolean Peinture::sculpt() {return false};

b) Utilisez cette méthode pour écrire en OQL la requête suivante :


Quels sont les artistes qui ont réalisé des peintures et des sculptures ?

1pt
Select a
Lettres initiales du Prénom et du Nom: page 5

From a in LesArtistes
o1 in a.oeuvres, o2 in a.oeuvres
Where o1.sculpt() and not o2.sculpt();

Exercice 2. XML DTD 3 pts


1) Les définitions suivantes sont-elles équivalentes ? (Les éléments B, C et D ont un contenu EMPTY).
Entourez la bonne réponse. Justifiez votre réponse si les définitions ne sont pas équivalentes.

<! ELEMENT A (B|C*)> et <! ELEMENT A (B|C)*>

OUI NON
Si NON, pourquoi ?

<! ELEMENT A (B*,B*)> et <! ELEMENT A (B*)>

OUI NON
Si NON, pourquoi ?

<! ELEMENT A (B ? | (C, D)*)> et <! ELEMENT A (( B? | C*), (B? | D*) ) >

OUI NON
Si NON, pourquoi ?

<! ELEMENT A (( B*,C) | D+)> et <! ELEMENT A ( B*, (C| D+)) >

OUI NON
Si NON, pourquoi ?

1pt
Non pour tous, sauf le 2eme

2) On considère la DTD suivante :

<! ELEMENT A ( (B | D+), (C?, D)*, ( ( C, (B | D) ) | B* ), (B | C) ) >


<! ELEMENT B EMPTY >
<! ELEMENT C (B, D?) >
<! ELEMENT D EMPTY >

a) Quel est le plus petit document conforme à la définition ci-dessus?

<A>….._ _ _ _

_____
Lettres initiales du Prénom et du Nom: page 6

0,5pt
<A><B/><B/></A> ou <A><D/><B/></A>

b) Les documents suivants sont-ils conformes à la définition de A ?

<A> <D/> <D/><D/><C><B/><D/></C><D/><B/><B/><B/></A>

Conforme : entourer OUI NON

Si non pourquoi ?:

0,5pt
oui

<A><B/><D/><C><B/><D/></C><B/><B/><B/></A>

Conforme : entourer OUI NON

Si non pourquoi ?:

0,5pt
Non, on ne peut pas avoir 3 B de suite après le C

<A><B/><C><B/></C><D/><C><B/></C><B/><D/><C><B/><D/></C></A>

Conforme : entourer OUI NON

Si non pourquoi ?:

0,5pt
Non, il y a un D en trop avant le dernier C

Exercice 3. SQL3 10 pts

On considère le schéma SQL3 suivant décrivant des jeux de tirage (loto, euro million, ...). Lire la 1ère colonne
puis la 2ème.
create type Cases as table of Number(2); create type Joueur as object (
/ prenom Varchar2(30), // le prénom est unique
create type Ticket as object ( achat Tickets
jeu Varchar2(30), );
combinaison Cases, /
jour Date, // la date du ticket ex. ’13-6-2014’ // Asso est un organisme (culturel, sportif, autre ...)
prix Number // le prix de vente create type Asso as object (
); nom Varchar2(30),
/ ville Varchar2(30)) not final;
create type Tickets as table of Ticket; /
/
Lettres initiales du Prénom et du Nom: page 7

1) A partir du type Asso, définir le type plus spécifique Club ayant plusieurs adhérents. Un joueur adhère à un
Club en se faisant parrainer par un joueur. On connait la date et le parrain pour chaque adhésion. Un joueur peut
adhérer à aucun ou plusieurs clubs. On connait le nom et la ville d’un club. Utiliser les termes de l’énoncé
autant que possible.

CREATE _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

create type Adhesion as object(


j ref Joueur,
parrain ref Joueur,
date_adhesion Date
);
@compile

create type Adhesions as table of Adhesion;


@compile

create type Club under Asso (


joueurs Adhesions);
@compile

2) Compléter la définition des tables LesJoueurs et LesClubs stockant les joueurs et les clubs respectivement.

Create table LesJoueurs

Create table LesClubs

create table LesJoueurs of Joueur


nested table achat store as t
(nested table combinaison store as c); double niveau d’imbrication

create table LesClubs of Club


nested table adherents store as a;
3a) Insérer, en SQL3, le joueur Alan qui a joué au loto le vendredi 13-12-2013 la combinaison (1,3,5,7,9) pour 2
euros, et le vendredi 13-6-2014 la combinaison (1,2,4,6,8,10) pour 12 euros.

INSERT INTO _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Lettres initiales du Prénom et du Nom: page 8

_ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

insert into LesJoueurs values(


Joueur('Alan', Tickets(Ticket('loto', Cases(1,3,5,7,9), '13-12-2013', 2),
Ticket('loto', Cases(1,2,4,6,8,10), '13-6-2014', 12))));
insert into LesJoueurs values(
Joueur('Bob', Tickets(Ticket('loto', Cases(5,7,9,13,17,19), '27-10-2014', 12),
Ticket('loto', Cases(13,40,41,42,43), '27-10-2014', 2),
Ticket('EuroM', Cases(13,50,51,52,53), '27-10-2014', 12))));

3b) Alan a aussi joué à l’EuroM le 14-12-2013 la combinaison (5,7,9,13,17) pour 5 euros. Ecrire cela en SQL3.

INSERT INTO _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _

_ _ _ _ _ _ _

VALUES ( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _

)
insert into table(select j.achat
from LesJoueurs j
where j.prenom='Alan')
values(Ticket('euroM', Cases(3,4,5,6,7,8), '28-10-2014', 12));
4a) En SQL3 : Quel est le prix total dépensé par Bob pour acheter ses tickets ?

Select _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

select sum(t.prix)
from LesJoueurs j, table(j.achat) t
where j.prenom ='Bob'
;
4b) En SQL3 : Lister, dans l’ordre croissant, tous les numéros déjà joués par Carole sur des tickets à 2 euros.

Select _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

select distinct value(c)


from LesJoueurs j, table(j.achat) t, table(t.combinaison) c
where t.prix = 2
and j.prenom=’Carole’
order by value(c);
Lettres initiales du Prénom et du Nom: page 9

5) On complète le schéma avec le type Stat représentant des statistiques d’utilisation des numéros.
create type Stat as object (
numero Number(2), // un numéro déjà joué
nbusage Number(3)); // le nombre de fois que le numéro a été joué
/
En SQL3, lister les numéros déjà joués au Loto, avec pour chacun leur nombre d’utilisations. Le résultat de la
requête doit être une liste d’objets Stat. Trier la liste par ordre décroissant du nombre d’utilisation.

Select _ _ _ _ _ _

From _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Where _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _

select Stat(value(c), count(*))


from LesJoueurs j, table(j.achat) t, table(t.combinaison) c
where t.nom=’loto’
group by value(c)
order by count(*) desc
;
6) On complète le schéma avec le type EnsStat suivant :
create type EnsStat as table of Stat;
On complète le type Joueur avec la méthode mesStat pour calculer les statistiques d’usage d’un joueur. La
signature est :
member function mesStat return EnsStat
Compléter le corps de la méthode :
member function mesStat return EnsStat is
resultat _ _ _ _ _ _;
begin
SELECT _ _ _ _ _ _ _ _

_ _ _ _ _ _ into resultat

FROM _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

return resultat;
end;
create or replace type body Joueur as
member function mesStat return EnsStat is
resultat EnsStat;
begin
select Stat(value(c), count(*))
bulk collect into resultat
from table(self.achat) a, table(a.combinaison) c
group by value(c)
-- order by count(*) desc // ne pas trier
;
return resultat;
end;
Lettres initiales du Prénom et du Nom: page 10

end;
7) Afficher les statistiques d’utilisation de chaque Joueur. Le résultat de la requête doit être une liste contenant
des couples dont le type est (prenom Varchar2, e EnsStat).

SELECT _ _ _ _ _ _ _ _ _ _ _

FROM _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _

select j.prenom, j.mesStat() as e


from LesJoueurs j
;

8) On suppose que chaque joueur a un seul numéro favori (c’est le numéro qu’il a joué le plus souvent).
Afficher le numéro favori de chaque joueur. Le résultat de la requête doit être une liste contenant des couples
dont le type est (prenom Varchar2, favori Number).

SELECT _ _ _ _ _ _ _ _

FROM _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

WHERE _ _ _ _ _ _ _ _ (SELECT _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ FROM _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _

select j.prenom, s.numero as favori


from LesJoueurs j, table(j.mesStat()) s
where s.nbusage= (select max( s2.nbusage)
from table(j.mesStat()) s2)
order by j.prenom, s.numero
;
9) (bonus). On complète le type Club avec la méthode statAdherents pour calculer les statistiques d’usage de
tous les adhérents du club
member function mesStat return EnsStat
Compléter le corps de la méthode, en invoquant la méthode mesStat() de Joueur.
member function statAdherents return EnsStat is
resultat _ _ _ _ _ _;
begin
SELECT _ _ _ _ _ _ _ _

_ _ _ _ _ _ into resultat

FROM _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

return resultat;
Lettres initiales du Prénom et du Nom: page 11

end;
create or replace type body Club as
member function statAdherents return EnsStat is
resultat EnsStat
begin

select Stat(s.numero, sum(s.nbusage))


bulk collect into resultat
from table(self.adherents) a, table(a.j.mesStat()) s
group by s.numero;
Nom : Prénom : page 1

Modèles Avancés pour les Bases de Données


MABD – MI005
Examen réparti du 6 janvier 2012
Version CORRIGEE
Exercice 1. DTD 5 pts
Question 1. On considère la DTD A.dtd suivante. Les éléments non définis sont vides.
<!ELEMENT A ((B |(C, D?) | E), ((D,(F,G)|B) | ((I,J)*, H+))* )>
a) Donnez le plus petit document XML conforme à cette DTD
<A><B/></A> ou <A><C/></A> ou <A><E/></A>
b) Pour chaque document D1 et D2 suivant, indiquez s’il est conforme à la DTD A.dtd ? S’il n’est pas conforme,
expliquez pourquoi.
D1 : <A><C/><F/><G/><B/><I/><J/><H/></A>
Non, doit contenir un D avant le F
D2 : <A><C/><D/><B/><H/><I/><J/><H/></A>
Oui, conforme
Question 2. On considère la DTD suivante :
<!DOCTYPE Etudiants [ <!ELEMENT Etudiants (Etudiant+)>
<!ELEMENT Etudiant (Post*, Amis)>
<!ATTLIST Etudiant Nom CDATA #REQUIRED>
<!ELEMENT Post (#PCDATA)>
<!ELEMENT Amis (Ami*)>
<!ELEMENT Ami (Nom)>
<!ELEMENT Nom (#PCDATA)>
]>
On veut utiliser le concept IDREF au lieu de la structure en sous-élément pour représenter les Amis. Modifier la
DTD en conséquence, en veillant à ce qu’elle soit le plus simple possible, sans perdre d’information.
Remarque : les amis d’un étudiant ne sont pas tous étudiants.
<!DOCTYPE Etudiants[
<!ELEMENT Etudiants (Etudiant+, Ami *)>
<!ELEMENT Etudiant ( Post*)>
<!ATTLIST Etudiant Nom CDATA #REQUIRED
Amis IDREFS #REQUIRED>
<!ELEMENT Post (#PCDATA)>
<!ELEMENT Ami EMPTY>
<!ATTLIST Ami Nom ID #REQUIRED>
]>

Question 3. On considère le schéma XML ci-dessous. Ce schéma est-il satisfait par exactement le même ensemble
de documents XML qui sont conformes à la DTD Etudiants de la question 2 ? Si la réponse est NON, expliquez
pourquoi.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Etudiants">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Etudiant">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Post" type="xsd:string"/>
<xsd:element name="Amis">
Lettres initiales du Prénom et du Nom: page 2

<xsd:complexType>
<xsd:sequence>
<xsd:element name="Ami">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Nom" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="Name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

Rép : Non, dans la DTD on peut avoir plusieurs éléments Etudiant dans Etudiants (Etudiant +), alors que dans le
schéma, on a maxoccurs = 1 par défaut..

Exercice 2 : Xquery et Xpath 10 pts


Soient « cat.xml », « price.xml » et « ord.xml » trois fichiers XML décrivant respectivement les catalogues des
produits par département, la liste des prix des produits et les différentes ventes des articles à une date donnée.
cat.xml
<catalog>
<product dept="WMN">
<number>557</number>
<name language="en">Linen Shirt</name>
<colorChoices>beige sage</colorChoices>
</product>
<product dept="ACC">
<number>563</number>
<name language="en">Ten-Gallon Hat</name>
</product>
<product dept="ACC">
<number>443</number>
<name language="en">Golf Umbrella</name>
</product>
<product dept="MEN">
<number>784</number>
<name language="en">Rugby Shirt</name>
<colorChoices>blue/white blue/red</colorChoices>
<desc>Our <i>best-selling</i> shirt!</desc>
</product>
</catalog>

price.xml
<prices>
<priceList effDate="2004-11-15">
<prod num="557">
Lettres initiales du Prénom et du Nom: page 3

<price currency="USD">29.99</price>
<discount type="CLR">10.00</discount>
</prod>
<prod num="563">
<price currency="USD">69.99</price>
</prod>
<prod num="443">
<price currency="USD">39.99</price>
<discount type="CLR">3.99</discount>
</prod>
<prod num="784">
<price currency="USD">25.99</price>
</prod>
</priceList>
</prices>

ord.xml
<order num="00299432" date="2004-09-15" cust="0221A">
<item dept="WMN" num="557" quantity="1" color="beige"/>
<item dept="ACC" num="563" quantity="1"/>
<item dept="ACC" num="443" quantity="2"/>
<item dept="MEN" num="784" quantity="1" color="blue/white"/>
<item dept="MEN" num="784" quantity="1" color="blue/red"/>
<item dept="WMN" num="557" quantity="1" color="sage"/>
</order>
A. XPATH (4 pts)
A.1) Evaluer les expressions XPATH suivantes sur les documents et donner le résultat obtenu.
document("ord.xml")//order/*[exists(@color)]/@*
Retourne uniquement les attributs des éléments « item » (nœud fils de order) qui au moins un attribut « color »
dept="WMN" num="557" quantity="1" color="beige"
dept="MEN" num="784" quantity="1" color="blue/white"
dept="MEN" num="784" quantity="1" color="blue/red"
dept="WMN" num="557" quantity="1" color="sage"
document("cat.xml")//product[* except (number | name) ]/@dept
Retourne les départements des produits ayant au moins un élément autre que number et name

dept="WMN" dept="MEN"
document("cat.xml")//product[position() mod 2 = 0]/number
Remarque: l’opérateur mod calcule le modulo.
Retourne uniquement le numéro des produits qui se trouvent en positions paires 2ème 4ème etc.
<number>563</number><number>784</number>

document("cat.xml")//colorChoices/parent::*[child::desc]/name
Retourne le nom des produits pères de colorchoices qui un fils « desc ».
<name language="en">Rugby Shirt</name>

A.2) Exprimer avec une seule expression XPATH les requêtes suivantes :
Parmi les produits du département ACC ayant leur numéro inférieur à 700, sélectionner uniquement le deuxième
produit.
doc("cat.xml")//product[number < 700 and @dept = "ACC"][2]
Lettres initiales du Prénom et du Nom: page 4

Les noms des produits du catalogue qui précèdent le produit numéro 443 (ses précédents frères).
document("cat.xml")//product/preceding-sibling::*[number=443]/name
Les prix des produits du catalogue ayant au moins un choix de couleur ‘bleu’.
doc("price.xml")//prod[@num=(doc("cat.xml")//product[contains(colorChoices,"blue")]/number)] /price

B. XQUERY (6 pts)
Ecrire les requêtes XQUERY permettant d’obtenir les informations suivantes :
1) Les noms des produits du département ACC triés suivant leurs noms. Le résultat de la requête doit être formaté
comme suit :
<ul type="square">
<li>Golf Umbrella</li>
<li>Ten-Gallon Hat</li>
</ul>
<ul type="square">
{
for $product in doc("cat.xml")/catalog/product
where $product/@dept='ACC'
order by $product/name
return <li>{data($product/name)}</li>
}
</ul>
2) Les différents numéros des produits. Les numéros des produits du département ACC sont encadrés par <acc>
</acc> et les autres par <other></other>. Le résultat de la requête doit être :
<results>
<other>557</other>
<acc>563</acc>
<acc>443</acc>
<other>784</other>
</results>

<results>
{
for $prod in (doc("cat.xml")/catalog/product)
return if ($prod/@dept = 'ACC')
then <acc>{data($prod/number)}</acc>
else <other>{data($prod/number)}</other>

}
</results>
3) Le numéro et le nom du produit le moins cher. Le résultat de la requête doit être :
<result> <product num="784" name="Rugby Shirt" minprice="25.99"/> </result>
<order>
{

let $prices:=document("price.xml")//prod/price
let $m:=min($prices)
for $np in document("price.xml")//prod[price=$m]/@num,
$pr in document("cat.xml")//product[number=$np]
return <product num="{$np}" name="{$pr/name}" minprice="{$m}" />

}
</order>
4) Les noms des produits du département “ACC” ou “WMN” dont le numéro de produit est supérieur à 100, ayant
au moins une couleur et dont le nom commence par la lettre L. Le résultat de la requête doit être :
<result> <name language="en">Linen Shirt</name> </result>
<result>
Lettres initiales du Prénom et du Nom: page 5

{
for $prod in document("cat.xml")//product
let $prodDept := $prod/@dept
where
$prod/number > 100 and
starts-with($prod/name, "L") and
exists($prod/colorChoices) and
($prodDept="ACC" or $prodDept="WMN")
return $prod/name
}
</result>
5) Le numéro, le nom, le prix de chacun des articles vendus et la quantité totale de ces articles regroupés par leur
numéro. Le résultat doit être trié par numéro croissant. Le résultat de la requête doit être :
<order>
<item num="443" name="Golf Umbrella" price="39.99" qte="2" />
<item num="557" name="Linen Shirt" price="29.99" qte="2" />
<item num="563" name="Ten-Gallon Hat" price="69.99" qte="1" />
<item num="784" name="Rugby Shirt" price="25.99" qte="2" />
</order>
<order>
{
for $item in distinct-values(doc("ord.xml")//item/@num)
let $it:=doc("ord.xml")//item[@num=$item],
$product:=doc("cat.xml")//product[number=$item],
$price:=doc("price.xml")//prod[@num=$item]
order by $item
return
<item num="{$item}" name="{$product/name}"
qte="{sum($it/@quantity)}"
price="{$price/price}"/>
}
</order>

6) Evaluer l’expression XQUERY suivante et donner le résultat obtenu.


<result>
{
for $d in distinct-values(doc("ord.xml")//item/@dept)
let $items := doc("ord.xml")//item[@dept = $d]
order by $d
return
<department code="{$d}">
{
for $n in distinct-values($items/@num)
let $qte := $items[@num =$n ]/@quantity
let $pr := doc("price.xml")//prod[@num =$n ]/price
let $dc := doc("price.xml")//prod[@num =$n]/discount
order by $n
return
if (exists($dc)) then
<item num="{$n}" price="{xs:decimal($pr)}" qte=" {sum($qte)"
discount="{xs:decimal($dc)}" totalPrice="{(xs:decimal($pr)*sum($qte))-$dc}" />
else
<item num="{$n}" price="{xs:decimal($pr)} "qte=" {sum($qte)} "discount="0"
totalPrice="{(xs:decimal($pr)*sum($qte))}" />
}
</department>
}
</result>

Le numéro, le prix unitaire, la quantité, la remise et le prix total des articles vendus par chaque département (totalPrice=[qte*
price]-discount).
<result>
Lettres initiales du Prénom et du Nom: page 6

<department code="ACC">
<item num="443" price="39.99 " qte="2 " discount="3.99" totalPrice="75.99"/>
<item num="563" price="69.99 " qte="1 " discount="0" totalPrice="69.99"/>
</department>
<department code="MEN">
<item num="784" price="25.99 " qte="2 " discount="0" totalPrice="51.98"/>
</department>
<department code="WMN">
<item num="557" price="29.99 " qte="2 " discount="10" totalPrice="49.98"/>
</department>
</result>

Exercice 3 : XML Schema 5 pts


Soit le document sport.xml décrivant brièvement des équipes de football et de basketball et les rencontres entre
équipes. Le document se décompose en deux parties. Tout d’abord, l’annuaire recense les équipes par sport et par
pays. Puis, l’historique des matchs récapitule, pour chaque coupe, les rencontres entre équipes. Il y a deux équipes
par match, une équipe peut jouer plusieurs matchs.
<?xml version="1.0" encoding="ISO-8859-1"?>
<sport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="sport.xsd">
<!-- annuaire des équipes-->
<foot>
<p nom="France">
<e>OM</e> <e>TFC</e> <e>OL</e> <e>PSG</e> <e>SL</e>
</p>
<p nom="Angleterre">
<e>Liverpool</e> <e>Arsenal</e> <e>Chelsea</e>
</p>
<p nom="Italie">
<e>Milan AC</e> <e>Juventus</e> <e>AS Roma</e>
</p>
</foot>
<basket>
<p nom="France">
<e>ASVEL</e> <e>PL</e> <e>Elan</e> <e>MSB</e>
</p>
<p nom="Angleterre">
<e>Trafford</e> <e>C.Jets</e> <e>M.Magic</e>
</p>
</basket>
<!--historique des matchs entre équipes-->
<coupeFoot>
<match> <e>TFC</e> <e>OM</e> </match>
<match> <e>Juventus</e> <e>PSG</e> </match>
<match> <e>Liverpool</e> <e>Milan AC</e> </match>
<match> <e>OM</e> <e>Juventus</e> </match>
</coupeFoot>
<coupeBasket>
<match> <e>C.Jets</e> <e>MSB</e> </match>
<match> <e>ASVEL</e> <e>Elan</e> </match>
<match> <e>ASVEL</e> <e>M.Magic</e> </match>
</coupeBasket>
</sport>

Le document sport.xsd est le schéma XML du document sport.xml. On donne une trame partielle du schéma
sport.xsd :
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sport">
Lettres initiales du Prénom et du Nom: page 7

<xs:complexType>
<xs:sequence>
<xs:element name="foot">
...
</xs:element>
...
</xs:sequence>
</xs:complexType>
...
</xs:element>
...
</xs:schema>

Question 1. On veut définir une contrainte pour vérifier qu’une équipe jouant un match de la coupe de foot est bien
recensée dans l’annuaire comme étant une équipe de foot. Par exemple, un match de foot entre PL et OM est
incohérent. Définir les éléments key et keyref exprimant cette contrainte et préciser quel est leur père.

Les éléments key et keyref ont pour père: <xs:element name="sport">

Le plus petit ancêtre commun permettant d’atteindre les équipes de l’annuaire et les
équipes jouant un match est l’élément sport.

Erreur à éviter : ne pas définir la clé dans l’élément foot, car ensuite on ne pourra
pas l’utiliser pour la keyref dans coupeFoot.

<xs:key name="cléFoot">
<xs:selector xpath="foot/p/e"/>
<xs:field xpath="."/>
</xs:key>

<xs:keyref name="matchFoot" refer="cléFoot">


<xs:selector xpath="coupeFoot/match/e"/>
<xs:field xpath="."/>
</xs:keyref>

Question 2. Définir une contrainte pour vérifier l’unicité globale du nom d’une équipe recensée dans l’annuaire,
tous sports et tous pays confondus. Définir l’élément et préciser quel est son père.
L’element unique a pour père <xs:element name="sport">

<xs:unique name="equipeUnique">
<xs:selector xpath="*/p/e"/>
<xs:field xpath="."/>
</xs:unique>

Autre possibilité pour le sélecteur : <xs:selector xpath="foot|basket/p/e"/>

Réponse erronnée
<xs:selector xpath=".//e"/>
Erreur car cela inclut à tort les éléments e des équipes jouant des matchs.

Question 3. Définir le schéma d’un match entre exactement deux équipes.


<xs:element name="match">
<xs:complexType>
<xs:sequence>
<xs:element ref="e" minOccurs="2" maxOccurs="2"/>
</xs:sequence>
</xs:complexType>
Lettres initiales du Prénom et du Nom: page 8

</xs:element>

Question 4. Définir le type typeEquipePoint de l’element e contenu dans l’élément match, de telle sorte que
l’élément e ait un attribut points dont la valeur est le nombre de points marqués par l’équipe pendant le match.
Exemple de contenu valide :
<match> <e points="0">TFC</e> <e points="3">OM</e> </match>

<xs:complexType name="typeEquipePoint">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="points" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>

Remarque : le type est ensuite utilisé pour définir un élément local :

<xs:element name="match">
<xs:complexType>
<xs:sequence>
<xs:element name="e" type="typeEquipePoint" minOccurs="2" maxOccurs="2">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>

Le type e est définit localement dans le contenu de l’élément match.


IL n’est pas en conflit avec l’autre type e contenu dans l’élément p pour l’annuaire
des équipes.
Rappel : en XML Schema on peut avoir plusieurs éléments de même nom mais de type
différent.
Nom : Prénom : page 1

Module Bases de Données et Web


Examen réparti du 4 novembre 2011
Version CORRIGEE

Les documents sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. La taille des cadres suggère celle de la réponse
attendue. Utiliser le dos de la feuille précédente si la réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité
de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet.

Exercice 1. SQL3 10 pts


On considère le schéma SQL3 suivant :
Create type Personne as object (
Nom varchar2(30),
Affiliation varchar2(30)
) ;
Create type EnsPersonnes as table of ref Personne ;

Create type Article as object (


Titre varchar2(50),
Auteurs EnsPersonnes
);
Create type EnsArticles as table of ref Article ;
Create type Conference as object (
Titre varchar2(50),
Lieu varchar2(30),
Dateconf number(4),
Participants EnsPersonnes,
Contient EnsArticles
) ;

Question 1. Définir les tables LesPersonnes, LesArticles et LesConferences

Create table LesPersonnes of Personne ;


Create table LesArticles of Article nested table auteurs store as T-auteurs;
Create table LesConferences of Conference
Nested table participants store as T-participants,
Nested table contient store as T-contient;
Question 2. On effectue les instructions suivantes :
Insert into LesPersonnes values( Personne(‘Max’, ‘UPMC’) );
Insert into LesPersonnes values( Personne( ‘Léa’, ‘P6’) );
Insert into LesArticles values ( Article(‘art1’, EnsPersonnes()) );
Lettres initiales du Prénom et du Nom: page 2

Ecrivez en SQL3 l’instruction permettant d’insérer la conférence de titre ‘BD et Web’, qui a lieu à Lyon
en 2010, à laquelle Max participe, et qui contient l’article ‘art1’.

Insert into LesConferences values (‘BD et Web’, ‘Lyon’, 2010, ensPersonnes ((select ref(p) from LesPersonnes p
where p.nom=’Max’)), ensArticles((select ref(a) from LesArticles a where a.titre=’art1’)));

Question 3. Ecrivez l’instruction SQL3 qui permet d’insérer Léa comme auteur de l’article ‘art1’.

Insert into table (select a.auteurs from LesArticles a where a.titre=’art1’) values ((select ref(p) from lesPersonnes p
where p.nom=’Léa’));
Question 4. Ecrivez en SQL3 les requêtes suivantes :
1. Noms des participants à la conférence ‘BD et Web’.

select

Select value(p).nom from lesCOnferences c, table(c.participants) p where c.titre=’BD et Web’;

2. Nombre de participants à la conference ‘BD et Web’;

select
Lettres initiales du Prénom et du Nom: page 3

Select count(value(p)) from LesConferences c, table(c.participants) p where c.titre =’BD et Web’;


3. Nom des auteurs des articles qui ne participent pas à la conférence où est publié leur article.

select

Select value(a).nom
from LesConferences c, table(c.contient) cont, table(value(cont).auteurs) a
where value(a) not in (select value(p) from table(c.participants) p);

REQUETE NON POSEE


Titre de la conférence qui a eu lieu en 2010 et qui contient l’article ‘art1’.
Réponse :
Select c.titre from LesConferences c, table (c.contient) cont
where c.dateconf=2010 and value(cont).titre=’art1’;;
Question 5. Avant qu’un article soit publié, il est évalué par plusieurs relecteurs (5 au maximum) qui lui attribuent
une note. Modifier le schéma initial pour avoir, pour chaque article, les relecteurs et la note que chacun a attribuée.
Par exemple, l’article ‘art1’ a été relu par Luc, qui a donné la note de 5 et par Marie, qui a donné la note de 4.

Drop type article ;


Create type evaluation as object (
relecteur ref Personne,
note number(2)
) ;
Create type ensevaluation as varray(5) of evaluation ;
Create type Article as object (
Titre varchar2(50),
Lettres initiales du Prénom et du Nom: page 4

Auteurs EnsPersonnes,
Eval ensevaluation
);
Comme il s’agit d’un varray, on n’a pas besoin de modifier la table LesArticles en
ajoutant une nested table. Si ensevaluation est defini comme une table, il faut
aussi modifier la table en ajoutant une nested table.

Exercice 2 : OQL 10 pts


Références: issu de l’ex OQL du partiel 2010

Soit le schéma ODL d’une base pour gérer les utilisateurs d’un réseau social. Un internaute possède un mur sur
lequel il partage ses photos. Un internaute peut commenter les photos des autres internautes. Un internaute peut
voter pour (avis positif) ou contre (avis négatif) une photo. Une photo peut être associée avec les personnes qui
apparaissent en portrait sur la photo. Un internaute a des amis directs, toujours mutuels. Les amis indirects,
éloignés d’un chemin de longueur d, sont appelés les proches, cf. la méthode proches(d).

interface Personne { keys mail; interface Mur { extent Murs; keys id;
attribute string mail; attribute string id;
attribute string nom; attribute string nom;
attribute string prénom; relationship Internaute propriétaire inverse Internaute::mur;
relationship set<Photo> paraît_sur inverse Photo::portrait_de relationship set<Photo> contient inverse Photo::sur;
}; Photo meilleur_avis();
set<Photo> x() ;
};
interface Internaute : Personne { extent Internautes;
attribute string login;
attribute long age;
attribute string ville;
relationship set<Internaute> amis inverse Internaute::amis;
relationship Mur mur inverse Mur::propriétaire;
set<Internaute> proches(long d);
};
interface Photo { extent Photos; keys numéro; interface Commentaire { keys numéro;
attribute long numéro ; attribute long numéro;
attribute string nom; attribute string nom;
attribute long hauteur; attribute string texte;
attribute long largeur; relationship Internaute écrit_par;
attribute long avis_positifs ; relationship Photo sujet
attribute long avis_négatifs ; inverse Photo::commentaires;
relationship Mur sur inverse Mur::contient; };
relationship set<Personne> portrait_de inverse Personne::paraît_sur;
relationship set<Commentaire> commentaires inverse Commentaire::sujet;
};

Question 1. Compléter le schéma en ajoutant une relation inverse pour la relation écrit_par de l’interface
Commentaire.

Dans l’interface Commentaire :


Relationship Internaute écrit_par inverse Internaute::commente

Dans l’interface Internaute :


Relationship set<Commentaire> ecrit inverse Commentaire::ecrit_par
Lettres initiales du Prénom et du Nom: page 5

Question 2. Dans cette question et les suivantes, on ignore la modification de schéma faite à la question 1. On
considère le schéma donné dans l’énoncé.
a) Combien de racines de persistance sont définies ?

3 racines Inernautes,Murs,Photos

b) La base peut-elle contenir des personnes qui ne sont pas des internautes ?

Oui, bien qu’il n’y ait pas de racine pour les Personnes,
il est possible d’atteindre toute les personnes qui apparaissent sur au moins une
photo.

Question 3. Ecrire en OQL les requêtes suivantes :


R1 : Afficher le nom des photos ayant au moins 5 avis positifs, et se trouvant sur le mur de l’internaute dont le mail
est ‘123@etu.upmc.fr’

select
from in
where
and

Select p.nom
From p in Photos
Where p.avis_positifs >5
And p.sur.propriétaire.mail= ‘123@etu.upmc.fr’

R2 : Afficher le mail des amis de l’internaute ayant mis une photo nommée ‘Tour Eiffel’ sur leur mur. Donner deux
réponses équivalentes, la première en utilisant la racine Internautes, la deuxième utilisant la racine Photos.

select
from i in Internautes
where

select
from p in Photos
where
Lettres initiales du Prénom et du Nom: page 6

Select a.mail
From i in Internautes, a in i.amis, p in i.mur.contient
Where p.nom = ‘Tour Eiffel’

Select a.mail
From p in Photos, a in p.sur.propriétaire.amis
Where p.nom = ‘Tour Eiffel’

R3: Afficher le nombre moyen de photos par mur. Rmq : la fonction avg() calcule la moyenne.

avg(select count(m.contient)
from m in Murs )

OU

select avg( select count(*)


from p in m.contient)
from m in Murs

OU

Select avg(count(partition))
From m in Murs, p in m.contient
Group by m

R4: Quels sont les internautes qui n’ont commenté aucune photos ?

select
from
where

Select
From i in Internautes
Where i not in (select p.écrit_par
From p in Photos, c in p.commentaires)

Autre possibilité avec un for all


Lettres initiales du Prénom et du Nom: page 7

R5 : Quel est le format (hauteur et largeur) de toutes les photos partagées sur les murs des amis de Jean Dupont ?

select p.largeur, p.hauteur


from i in Internautes, a in i.amis, p in a.mur.contient
where i.nom= ‘Dupont’ and i.prénom=’Jean’

Autre solution (en utilisant 2 racines


Select p.largeur, p.hauteur
from m in Murs, p in m.contient, i in Internautes, a in i.amis
where i.nom= ‘Dupont’ and i.prénom=’Jean’
and m.propriétaire = a

Question 4
Ecrire le corps de la méthode top_commentaire() qui retourne la ou les photos ayant le plus grand nombre de
commentaires, parmi les photos mur en question.
Set<Photo> Mur::top_commentaire () {

}
Photo Mur::top_commentaire() {

return (select p
from p in this.contient
where count(p.commentaire) = (
select max(p1.commentaire)
from p1 in this.contient)
)
}

Autre solution avec >= ALL

Question 5
a) Expliquer ce que retourne la méthode y() définie ci-dessous. Quel est l’inconvénient majeur de cette méthode ?
Lettres initiales du Prénom et du Nom: page 8

set<Photo> Mur::y() {
return (this.contient
union
select distinct p
from a in this.propriétaire.amis, p in a.mur.y());
}

La méthode y retourne les photos d’un mur d’un internaute et celles de ses amis
directs et indirects. Problème : fin de la récursion ?

b) Ecrire le corps de la méthode proches(d) qui retourne l’ensemble des amis (et amis d’amis par transitivité)
atteignables par un chemin de longueur inférieure ou égale à d. Remarque : si nécessaire vous pouvez utiliser une
instruction conditionnelle if then else endif.
set<Internaute> Internaute::proches(long d) {

}
Set<Internaute> Internaute::proche(int d)

if(d>1) then
Return ( this.amis
union
Select distinct b
From a in this.amis, b in a.proches(d-1)
)
Lettres initiales du Prénom et du Nom: page 9

Else
Return (this.amis)
End if;

QUESTION NON POSEE


c) Etant donné une personne A, on veut déterminer l’ensemble E des personnes
qui apparaissent soit sur la même photo que A, soit sur la même photo que
quelqu’un appartenant à E. Expliquer brièvement comment obtenir E.

Réponse :
Fermeture transitive de la relation : pi ‘ est sur la même photo que pj

On ajoute la méthode auxilliaire m() pour implémenter la relation « est sur la même
photo»

Set<Personne> Personne::m() {
return (select distinct pers
from ph in this.paraît_sur, pers in ph.portrait_de
}

On détermine l’ensemble E à l’aide de la méthode récursive e()

Initialisation: Set<Personne> visité = (A);


Invocation: A.e(visité) ;

Attention, il faut détecter les cycles sinon ça ne se termine pas.

Set<Personne> Personne::e( set<Personne> visitées) {

// les personnes à visiter (moins celles qui ont déjà été visitées)
Set <Personne> à_visiter = select p
From p in m()
Where p not in visitées;

Ou à visiter = m() minus visitées;

// compléter les personnes visitées


Visitées = Visitées union m() ;

return à visiter
union (select distinct q
from p in à_visiter, q in p.e(visitées) )
}
Nom : Prénom : page 1 Lettres initiales du Prénom et du Nom: page 2

Module Bases de Données et Web


Examen réparti du 5 novembre 2010
Les documents sont autorisés – Durée : 2h.
Répondre aux questions sur la feuille du sujet dans les cadres appropriés. La taille des cadres suggère celle de la réponse Question 3. Effectuez les insertions suivantes :
attendue. Utiliser le dos de la feuille précédente si la réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité
de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet. Le pays France, dont la capitale est Paris, qui a Lyon comme ville principale et qui comporte 62 000 000
habitants ; (pour le moment, le champ limites est vide).
Exercice 1. SQL3 12 pts
On considère le schéma SQL3 suivant :
Create type T_Pays ;
Create type T_frontiere as object (
Pays ref T_Pays,
Lg number
) ;
Create type Ensfrontieres as table of T_frontiere ;
La ville de Marseille, en France, qui comporte 900 000 habitants ;
Create type T_Ville as object (
Nom varchar2(30),
Pays ref T_Pays,
Population number
);
Create type EnsVilles as table of ref T_Ville;
Create type T_Pays as object (
Nom varchar2(30), Insérez la ville de Marseille dans les villes principales de France ;
Capitale ref T_Ville,
villesPrincipales EnsVilles,
population number,
limites Ensfrontieres
) ;
Create type EnsPays as table of ref T_Pays;

Insérez le pays Belgique, qui a Bruxelles comme capitale, qui a 10 000 000 habitants, et qui a une frontière
Create table LesVilles of T_Ville;
avec la France de 620 km de long.
Insert into LesVilles values(‘Paris’, NULL, 2000000);
Insert into LesVilles values (‘Lyon’, NULL, 500000);
Insert into LesVilles values (‘Bruxelles’, NULL, 1000000);

Question 1. Définir un type T_Federation qui a un nom et un ensemble de pays membres.

Insérez la fédération nommée FB, qui comporte la France et la Belgique ;

Question 2. Définir les tables LesPays et LesFederations permettant de stocker les instances de T_Pays et
T_Federation respectivement.
Lettres initiales du Prénom et du Nom: page 3 Lettres initiales du Prénom et du Nom: page 4

Question 4. Ecrivez en SQL3 les requêtes suivantes :


1. Pour chaque pays, calculez la longueur de ses frontières. Exercice 2 : OQL 8 pts
Soit le schéma ODL d’une base pour gérer les utilisateurs d’un réseau social. Un internaute possède un mur sur
lequel il partage ses photos. Un internaute peut commenter les photos des autres internautes. Un internaute peut
select voter pour (avis positif) ou contre (avis négatif) une photo. Une photo peut être associée avec les personnes qui
apparaissent en portrait sur la photo. Un internaute a des amis directs, toujours mutuels. Les amis indirects,
éloignés d’un chemin de longueur d, sont appelés les proches, cf. la méthode proches(d).
from
interface Personne { keys mail; interface Mur { extent Murs; keys id;
attribute string mail; attribute string id;
... attribute string nom; attribute string nom;
attribute string prénom; relationship Internaute propriétaire inverse Internaute::mur;
relationship set<Photo> paraît_sur inverse Photo::portrait_de relationship set<Photo> contient inverse Photo::sur;
}; Photo meilleur_avis();
2. Nom des pays frontaliers de la Belgique, et le nom de leur capitale. set<Photo> x() ;
};
interface Internaute : Personne { extent Internautes;
select attribute string login;
attribute long age;
attribute string ville;
from relationship set<Internaute> amis inverse Internaute::amis;
relationship Mur mur inverse Mur::propriétaire;
set<Internaute> proches(long d);
};
where
interface Photo { extent Photos; keys numéro; interface Commentaire { keys numéro;
attribute long numéro ; attribute long numéro;
attribute string nom; attribute string nom;
attribute long hauteur; attribute string texte;
3. Nom des villes principales des pays membres de la fédération FB. attribute long largeur; relationship Internaute écrit_par;
attribute long avis_positifs ; relationship Photo sujet
attribute long avis_négatifs ; inverse Photo::commentaires;
relationship Mur sur inverse Mur::contient; };
select relationship set<Personne> portrait_de inverse Personne::paraît_sur;
relationship set<Commentaire> commentaires inverse Commentaire::sujet;
};
from
Question 1. Ecrire en OQL les requêtes suivantes :
R1 : Quel est le nom des photos commentées par l’internaute dont le login est ‘jb007’ et qui habite à Paris?
where

4. Nom des pays qui ont plus de 3 villes de plus de 100 000 habitants (on considère que la capitale est comprise
dans la liste des villes principales)

select
R2 : Quels sont les internautes qui ont commenté au moins une photo d’un de leurs amis ? Afficher le login des
internautes en question. Donner deux réponses équivalentes, la première en utilisant la racine Internautes, la
from deuxième utilisant la racine Photos.

where select
from i in Internautes
where
Lettres initiales du Prénom et du Nom: page 5 Lettres initiales du Prénom et du Nom: page 6

select
from p in Photos
where

R3 : Pour chaque internaute, combien a-t-il d’amis? Afficher le login de l’internaute et son nombre d’amis.

b) Ecrire le corps de la méthode proches(d) qui retourne l’ensemble des amis (et amis d’amis par transitivité)
atteignables par un chemin de longueur inférieure ou égale à d. Remarque : si nécessaire vous pouvez utiliser une
instruction conditionnelle if then else endif.
set<Internaute> Internaute::proches(long d) {

R4 : Quel est le format (hauteur et largeur) de toutes les photos partagées sur les murs des amis de Robin Débois ?

Question 2
Ecrire le corps de la méthode meilleur_avis() qui retourne la photo ayant le plus grand score, parmi les photos dudit
mur. Le score d’une photo est calculé avec la formule : score = avis_positifs – avis_négatifs.
Photo Mur::meilleur_avis() { }
c) Etant donné une personne A, on veut déterminer l’ensemble E des personnes qui apparaissent soit sur la même
photo que A, soit sur la même photo que quelqu’un appartenant à E. Expliquer brièvement comment obtenir E.

Question 3
a) Expliquer ce que retourne la méthode x() définie ci-dessous. Quel est l’inconvénient majeur de cette méthode ?
set<Photo> Mur::x() {
return (this.contient
union
select distinct p
from a in this.propriétaire.amis, p in a.mur.x());
}
Nom : Prénom : page 1

Module Bases de Données et Web


Examen réparti du 13 novembre 2009
Version CORRIGEE

Les documents sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. La taille des cadres suggère celle de la réponse
attendue. Utiliser le dos de la feuille précédente si la réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité
de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet.

Exercice 1 : Requêtes avancées sur la base MONDIAL 6pts


Le schéma relationnel suivant est extrait de la base MONDIAL vu en TD:

Continent (Name, Area)


Country (Name, Code, Capital, Province, Area, Population) // Province est la région de la capitale

Encompasses (Country, continent, percentage) // pourcentage de 0 à 100


Borders (Country1, Country2, length) // cette relation est asymétrique. On a (F, I, ...) pour France-Italie et (E,F,...) pour Espagne-France.
Country1< Country2 selon l’ordre lexicographique.

Language (Country, Name, Percentage) // pourcentage de 0 à 100


Religion (Country, Name, Percentage) // pourcentage de 0 à 100

Sea (Name, Depth)


Geo_Sea (Sea, Country, Province)

Ecrire en SQL les requêtes suivantes


1. Le(s) pays ayant la plus grande frontière avec la france (sans group by) (1pt)
Lettres initiales du Prénom et du Nom: page 2

select c2.name, b.length as longueur_frontiere


from country c1, country c2, borders b
where c1.name = 'France'
and
(
(c1.code = b.country1
and c2.code = b.country2)
or
(c1.code = b.country2
and c2.code = b.country1)
)
and b.length >= ALL (select b1.length
from country c3, borders b1
where
(
(c1.code = b1.country1
and c3.code = b1.country2)
or
(c1.code = b1.country2
and c3.code = b1.country1)
))
;

-- la même mais sans ALL

select c2.name, b.length as longueur_frontiere


from country c1, country c2, borders b
where c1.name = 'France'
and
(
(c1.code = b.country1
and c2.code = b.country2)
or
(c1.code = b.country2
and c2.code = b.country1)
)
and not exists (select *
from country c3, borders b1
where b1.length > b.length and
(
(c1.code = b1.country1
and c3.code = b1.country2)
or
(c1.code = b1.country2
and c3.code = b1.country1)
))
;
Lettres initiales du Prénom et du Nom: page 3

2. Les pays frontaliers de la France avec, pour chacun, le nombre de pays voisins (0,5pt)

select c2.name, count(c3.code) as nbvoisins


from country c1, country c2, country c3, borders b, borders b1
where c1.name = 'France'
and
(
(c1.code = b.country1
and c2.code = b.country2)
or
(c1.code = b.country2
and c2.code = b.country1)
)
and
(
(c3.code = b1.country1
and c2.code = b1.country2)
or
(c3.code = b1.country2
and c2.code = b1.country1)
)
group by c2.name;
Lettres initiales du Prénom et du Nom: page 4

3. Combien de gens dans le monde ont le français pour langue officielle ? (0,5pt)

select SUM(c1.population * l.percentage / 100)


from country c1, language l
where l.country=c1.code and l.name = 'French';
4. Quelle(s) religion(s) sont pratiquées dans tous les continents ? (1pt)

select distinct r.name


from religion r
where not exists
(select * from continent co where not exists
(select * from country c, encompasses e, religion r1
where e.country=c.code and e.continent = co.name
and r1.name=r.name and r1.country=c.code));
Lettres initiales du Prénom et du Nom: page 5

5. Quel(s) continent(s) a(ont) une densité moyenne supérieure à 30 ? (1pt)

select e.continent
from country c, encompasses e
where e.country=c.code
group by e.continent
having SUM(c.population)/SUM(c.area) > 30 ;

6. Quelle est la mer la plus profonde qui baigne l’Afrique ? (1pt)


Lettres initiales du Prénom et du Nom: page 6

select distinct s.name, s.depth, c.name


from sea s, geo_sea g, encompasses e, country c
where e.country=c.code and e.continent='Africa' and g.country=c.code and g.sea=s.name
and s.depth =
(select MAX(s1.depth)
from sea s1, geo_sea g1, encompasses e1, country c1
where e1.country=c1.code and e1.continent='Africa' and g1.country=c1.code and g1.sea=s1.name);

7. Couples de pays voisins partageant au moins une langue à plus de 30% (1pt)

select distinct c1.name, c2.name


from country c1, country c2, borders b, language l1, language l2
where b.country1=c1.code and b.country2=c2.code and l1.country=c1.code and l2.country=c2.code and
l1.percentage > 30 and l2.percentage > 30 and l1.name=l2.name order by c1.name ;

Exercice 2. SQL3 : modélisation 3 pts


On considère le schéma relationnel suivant extrait de la base MONDIAL (vue en TD):
Continent (Name, Area)
Country (Name, Code, Capital, Province, Area, Population) // Province est la région de la capitale

Province (Name; Country, Population, Area, Capital)


Lettres initiales du Prénom et du Nom: page 7

City (Name, Country, Province, Population, Longitude, Latitude)


Encompasses (Country, continent, percentage)
Borders (Country1, Country2, length) // cette relation est asymétrique. On a (F, I, ...) pour France-Italie et (E,F,...) pour Espagne-France.
Country1< Country2 selon l’ordre lexicographique.

On souhaite migrer cette base vers le relationnel-objet. Dans ce nouveau schéma, les données sont
stockées dans 4 tables (TheContinents, TheCountries, TheProvinces, TheCities) uniquement. Aucune
autre table ne doit être créée.
Définissez en SQL3 les types et les tables permettant cette migration, (en maximisant le partage d’objets
dès que possible). Toutes les informations du schéma relationnel doivent être conservées.
Lettres initiales du Prénom et du Nom: page 8

create type Continent as object (


name varchar2(20),
Area number );

create type encompasses as object (


cont ref Continent,
pourcentage number);
/
create type EnsEncompasses as table of encompasses;
/
create type Country;
/
create type City;
/
create type Province;
/
create type border as object (
pays ref Country,
length number);
/
create type EnsBorder as table of border;
/
create type Country as object (
name varchar2(30),
Lettres initiales du Prénom et du Nom: page 9

code number,
capital ref City,
prov ref Province,
Area number,
population number,
estdans EnsEncompasses,
frontieres EnsBorder);
/
create type Province as object (
name varchar2(30),
pays ref Country,
population number,
area number,
capital ref City );
/
create type City as object (
name varchar2(30),
pays ref Country,
prov ref Province,
population number,
longitude number,
latitude number);
/
create table TheContinents of Continent;

create table TheCountries of Country


nested table estdans store as lescontinents,
nested table frontieres store as lesfrontieres;

create table TheProvinces of Province;

create table TheCities of City;

Exercice 3. SQL3 : mise à jour et interrogation 4 pts


On considère le schéma objet-relationnel suivant :
create type Personne;

create type Ville as object (


nom varchar2(30),
codePostal varchar2(5));

create type Maison as object (


numero number,
rue varchar2(30),
situe ref Ville);

create type EnsMaisons as table of ref Maison;


create type EnsParents as varray(2) of ref Personne;

create type Personne as object (


nom varchar2(20),
prenom varchar2(20),
age number(3),
habite EnsMaisons,
conjoint ref Personne,
parents EnsParents );
Lettres initiales du Prénom et du Nom: page 10

create table LesPersonnes of Personne


nested table habite store as habitations;
create table LesVilles of Ville;
create table LesMaisons of Maison;

On suppose que la base contient deux personnes, Max Traide et Annie Malle, les villes de Clamecy et de
Paris ainsi que les maisons 20 rue du Bac à Paris et 36 rue Chaude à Clamecy.,

Question 1 (2 pts)
De nouvelles informations doivent être ajoutées à la base :
Max Traide et Annie Malle sont mariés. Ils ont un fils, Jean Traide, qui a 30 ans, et qui habite 20 rue du
Bac, à Paris 7ème.
Ecrivez les instructions SQL3 permettant d’intégrer ces informations à la base.

Mariage de Max Traide et Annie Malle :

update LesPersonnes p
set p.conjoint = (select ref(i)
from LesPersonnes i where i.nom='Traide' and i.prenom='Max')
where p.nom='Malle' and p.prenom='Annie';

update LesPersonnes p
set p.conjoint = (select ref(i) from LesPersonnes i where i.nom='Malle' and
i.prenom='Annie')
where p.nom='Traide' and p.prenom='Max';

insertion de leur fils Jean Traide :


insert into LesPersonnes values
Lettres initiales du Prénom et du Nom: page 11

(Personne ('Traide', 'Jean', 30,


EnsMaisons((select ref(m) from LesMaisons m where m.rue='du Bac' and m.numero=20
and m.situe.nom='Paris' and m.situe.co
dePostal='75007')),
NULL,
EnsParents((select ref(p) from LesPersonnes p where p.nom='Malle' a
nd p.prenom='Annie'), (select ref(p) from LesPersonnes p where p.nom='Traide' and
p.prenom='Max'))));

Question 2 (2 pts)
Ecrivez en SQL3 les requêtes suivantes :

1. Nom et prenom du conjoint de Max

select p.nom, p.prenom from LesPersonnes p where p.conjoint.prenom='Max';

2. Prenom des personnes qui habitent avec leur conjoint ---

select p.prenom from LesPersonnes p where p.habite in p.conjoint.habite;


3. Adresse (numero, rue, nom de la ville et code postal) de Jean Traide ---

select value(h).numero, value(h).rue, value(h).situe.nom, value(h).situe.codePostal


from les Personnes p, table(p.habite) h
where p.nom='Traide' and p.prenom='Jean';

4. Nom des personnes qui habitent Paris

Select p.nom from LesPersonnes p, table(p.habite) m where


value(m).situe.nom='Paris';
Nom : Prénom : page 1

Module Bases de Données et Web


Examen du 20 décembre 2007
Version CORRIGEE

Les documents sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. La taille des cadres suggère celle de la réponse
attendue. Utiliser le dos de la feuille précédente si la réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité
de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet.

Exercice 1 : XML et DTD 4 pts


Une association musicale souhaite exporter vers un fichier XML la gestion de ses salles de concerts, dont
le schéma Entité-Association (E/A) est donné ci-dessous.

date heure

Oeuvre Orchestre
Nom 1:N 1:N Chef
concert
Auteur
Genre
Durée

1:N

Musicien
Mus-id composition
Nom 1:1
Instrument

Question 1. Ecrire une DTD décrivant cette structure pour le fichier XML. L’élément racine est l’élément
Programme, et contient des Concerts. Les entités E/A (musicien, orchestre, œuvre) seront représentées
par des éléments. Les attributs E/A sont représentés par des attributs.
(1) <?xml version ="1.0" encoding="ISO-8859-1" ?>
(2)< !ELEMENT Programme (
(3)
(4)
(5)
(6)
(7)
(8)
(9)
(10)
(11)
(12)
(13)
(14)
Lettres initiales du Prénom et du Nom: page 2

(15)
(16)
(17)
(18)
(19)
(20)
(21)
(22)
(23)
(24)

<?xml version ="1.0" encoding="ISO-8859-1" ?>


< !ELEMENT Salles ((concert) *)>
< !ELEMENT concert (orchestre, (œuvre)*)>
< !ATTLIST concert date CDATA #REQUIRED
heure CDATA #REQUIRED>
< !ELEMENT orchestre ((musicien)*)>
< !ATTLIST orchestre chef ID #REQUIRED>
< !ELEMENT œuvre EMPTY>
< !ATTLIST œuvre titre CDATA #REQUIRED
auteur CDATA #REQUIRED
genre CDATA #REQUIRED
duree CDATA #IMPLIED>
< !ELEMENT musicien EMPTY>
< !ATTLIST musicien id-mus ID #REQUIRED
nom CDATA #REQUIRED
instrument CDATA #REQUIRED
joue-dans IDREF #REQUIRED>

Question 2. Exprimez (lorsque c’est possible) les contraintes suivantes sur la DTD. (Si la contrainte est
déjà exprimée dans votre DTD, indiquez le numéro de ligne qui la définit.
1. Un concert comprend au moins 2 et au plus 5 œuvres

< !ELEMENT concert (orchestre, (œuvre, œuvre, œuvre+, œuvre+, œuvre+, ))>
Lettres initiales du Prénom et du Nom: page 3

2. Un concert est identifié de façon unique par la date et l’heure.

impossible
3. Le genre d’une œuvre est ‘concerto’, ‘symphonie’ ou ‘opéra’

< !ATTLIST œuvre type ("concerto"|"symphonie" |"opéra") "concerto" >


4. Un musicien joue dans un et un seul orchestre

< !ATTLIST musicien joue-dans IDREF #REQUIRED>

Exercice 2 : XSchema 6 pts


On souhaite maintenant modéliser l’application de l’exercice précédent à l’aide de Xschema. L’élément
racine est l’élément Programme, qui contient un ensemble de Concerts.
Question 1.
1. Définir le type TypeOeuvre pour représenter les Œuvres en utilisant uniquement des attributs.
L’attribut genre prend les valeurs "concerto", "symphonie" ou "opéra".
Lettres initiales du Prénom et du Nom: page 4

<xs :complexType name="TypeOeuvre">


<xs :attribute name="titre" type="xs :string"/>
<xs :attribute name="auteur" type="xs :string"/>
<xs :attribute name="genre" use="required">
<xs :simpleType>
<xs :restriction base ="xs :string"/>
<xs :enumeration value="concerto"/>
<xs :enumeration value="symphonie"/>
<xs :enumeration value="opera"/>
</xs:simpleType>
<xs :attribute name="duree" type="xs :integer"/>
</xs :complexType>
2. A partir du type TypeOeuvre, définir un type TypeOeuvreAvecInstruments contenant la liste des noms
des instruments pour lesquels l’œuvre a été écrite. Par exemple, une sonate en trio est écrite pour un
violon, un violoncelle et une flûte.
Lettres initiales du Prénom et du Nom: page 5

<xs :complexType name="TypeOeuvreAvecInstruments">


<complexContent>
<xs :extension base="TypeOeuvre">
<xs :sequence maxOccurs="unbounded">
<xs :element name="instrument" type="xs :string">
</xs:sequence>
<xs :attribute name="titre" type="xs :string" use="required"/>
<xs :attribute name="auteur" type="xs :string"/>
<xs :attribute name="genre" >
<xs :simpleType>
<xs :restriction base ="xs :string"/>
<xs :enumeration value="concerto"/>
<xs :enumeration value="symphonie"/>
<xs :enumeration value="opera"/>
</xs:simpleType>
</xs :attribute>
<xs :attribute name="duree" type="xs :integer" use="required"/>
</xs:extension>
</xs:complexContent>
</xs :complexType>
3. A partir du type TypeOeuvreAvecInstrument, définir le type MusiquedeChambre qui caractérise les
œuvres n’ayant pas plus de 5 instruments.
Lettres initiales du Prénom et du Nom: page 6

<xs :complexType name="MusiquedeChambre">


<xs :complexContent>
<xs :restriction base="TypeOeuvreAvecInstrument">
<xs :sequence maxOccurs="5">
<xs :element name="instrument" type="xs :string"/>
</xs:sequence>
<xs :attribute name="titre" type="xs :string" use="required"/>
<xs :attribute name="auteur" type="xs :string" use="required"/>
<xs :attribute name="genre" use="required" >
<xs :simpleType>
<xs :restriction base ="xs :string"/>
<xs :enumeration value="concerto"/>
<xs :enumeration value="symphonie"/>
<xs :enumeration value="opera"/>
</xs:simpleType>
</xs :attribute>
<xs :attribute name="duree" type="xs :integer" use="required"/>
</xs:restriction>
</xs:complexContent>
</xs :complexType>

Question 2. Définir l’élément concert, en représentant date et heure par des attributs. On utilisera le type
TypeOrchestre défini ci-dessous pour l’élément orchestre.
<xs :complexType name="TypeOrchestre ">
<xs:attribute name="chef" type="xs:string" use="required"/>
</xs:complexType>
Lettres initiales du Prénom et du Nom: page 7

<xs :element name="concert">


<complexType>
<xs :sequence>
<xs :element name="orchestre " type= "TypeOrchestre"/>
<xs : element name="œuvre" type="TypeOeuvre" maxOccurs="unbounded"/>
</xs :sequence>
<xs :attribute name="date" type="xs :string" use="required"/>
<xs:attribute name="heure" type="xs:integer" use="required"/>
<:xs:complexType>
</xs:element>
Question 3. On veut exprimer la contrainte qu’un concert est identifié de façon unique par la date et
l’heure.
a) dans quel élément doit-on définir cette contrainte ?

elle doit être définie à la fin de l’élément Programme


b) écrivez cette contrainte en Xschema
Lettres initiales du Prénom et du Nom: page 8

<xs :unique name="cleconcert">


<xs :selector xpath="/concert" />
<xs :field xpath="@date"/>
<xs:field xpath="@heure"/>
</xs:unique>
Question 4. Définir le type TypeInstrument qui est une chaîne de caractère de longueur 50

<simpleType name= "TypeInstrument ">


<xs :restriction base= "xs :string ">
<xs :length value="50"/>
</xs:restriction>
</xs:simpleType>
Question 5.
Définir l’élément musicien, en exprimant l’association joue-dans à l’aide d’un élément.
Lettres initiales du Prénom et du Nom: page 9

<xs :element name="musicien">


<xs :complexType>
<xs:sequence>
<xs:element name="joue-dans" type="xs:string" />
</sequence>
<xs :attribute name="mus-id" type="xs :integer" use ="required"/>
<xs:attribute name="nom" type="xs:string" use="required"/>
<xs:attribute name="instrument" type="TypeInstrument" use="required"/>
</xs:complexType>
</xs:element>
Question 6. Exprimez lorsque c’est possible les contraintes suivantes :
1. Un concert comprend au moins 2 et au plus 5 œuvres

<xs : element name="œuvre" type="TypeOeuvre" minOccurs="2" maxOccurs="5"/>

2. Les pianistes jouent dans un et un seul orchestre. (On suppose que l’élément Orchestre a une clef
nommée cléorchestre dont la valeur est le nom du chef )

<xs:sequence> par défaut minOccurs et maxOccurs sont 1


<xs:element name="joue-dans" type="xs:string" />
Lettres initiales du Prénom et du Nom: page 10

</sequence> ne suffit pas car rien ne dit que string est un orchestre.

On peut aussi utiliser keyref (à définir dans l’élément racine):


<xs :keyref name="unseulorchestre" keyref ="cleorchestre" >
<xs:selector xpath="//musicien[instrument="piano" ]/joue-dans" />
<xs:field xpath ="."/>
</xs:keyref>

Un orchestre a un et un seul pianiste

Exercice 3 : XPath 5 pts

Soit la DTD d’un catalogue de disques de musique classique suivante:


<!ELEMENT listeCD ((CD)+)>
<!ELEMENT CD (titre, compositeur, (morceau)+, editeur, (durée)?)>
<!ELEMENT morceau (titre, (soliste)*,(orchestre, chefdorchestre)?)>
<!ELEMENT soliste (Nom, Prenom, age, instrument)>
<!ELEMENT compositeur (Nom, Prenom)>
<!ELEMENT chefdorchestre (Nom, Prenom,age)>
<!ELEMENT editeur (#PCDATA)>
<!ELEMENT durée (#PCDATA)>
<!ELEMENT titre (#PCDATA)>
<!ELEMENT orchestre (#PCDATA)>
<!ELEMENT Nom (#PCDATA)>
<!ELEMENT Prenom (#PCDATA)>
<!ELEMENT Instrument (#PCDATA)>

Question 1. Exprimez en XPath les requêtes suivantes :


1. Tous les titres de morceaux interprétées avec un et un seul soliste et comportant le mot "symphonie ".
Lettres initiales du Prénom et du Nom: page 11

1 point
//morceau[soliste][not(soliste[2])]/titre[contains(., "symphonie")]
2. Prénom des chefs d’orchestre ayant dirigé le pianiste soliste "Raymond Charles " (le prénom est
Raymond)

1 point
//morceau[soliste[instrument="piano" and prenom="Raymond" and nom="Charles"]]/chefdorchestre/prenom
3. Prénom des solistes ayant joué avec l’orchestre "OMPF" (Orchestre de Mélodicas de la Place des
Fêtes) sur un disque édité par Syno.

1 point
//CD[editeur="Syno"]/morceau[orchestre="OMPF"]/soliste/Prenom
4. Titre des CD où le pianiste Raymond Charles interprète plus de morceaux que l’OMPF.

1 point
//CD[count(morceau[soliste[nom= "Raymond" and prenom="Charles" and instrument ="piano"] ] )
> count(morceau[orchestre="OMPF"])]/titre
4.
5. Titre des CD comportant au moins un morceau dirigé par un chef d’orchestre plus jeune que la
moyenne des solistes du même morceau.

1 point
//CD[morceau[avg(soliste/age) > chefdorchestre/age]]/titre
Lettres initiales du Prénom et du Nom: page 12

Exercice 4 : XQuery 5 pts


Soit le fichier XML book.xml suivant. Ce fichier comporte un seul livre qui lui-même contient des
sections de niveau 1 qui contiennent des sections de niveau 2.

book.xml <section id="syntax" difficulty="medium">


<?xml version="1.0"?> <title>A Syntax For Data</title>
<book> <p>Text ... </p>
<title>Data on the Web</title> <figure height="200" width="500">
<author>Serge Abiteboul</author> <title>Graph representations of structures</title>
<author>Peter Buneman</author> <image source="graphs.gif"/>
<author>Dan Suciu</author> </figure>
<section id="intro" difficulty="easy"> <p>Text ... </p>
<title>Introduction</title> <section>
<p>Text ... </p> <title>Base Types</title>
<section> <p>Text ... </p>
<title>Audience</title> </section>
<p>Text ... </p> <section>
</section> <title>Representing Relational Databases</title>
<section> <p>Text ... </p>
<title>Web Data and the Two Cultures</title> <figure height="250" width="400">
<p>Text ... </p> <title>Examples of Relations</title>
<figure height="400" width="400"> <image source="relations.gif"/>
<title>Traditional client/server architecture</title> </figure>
<image source="csarch.gif"/> </section>
</figure> <section>
<p>Text ... </p> <title>Representing Object Databases</title>
</section> <p>Text ... </p>
</section> </section>
</section>
</book>

Ecrire en XQuery les requêtes suivantes :


1. Donner la table des matières au niveau 1 pour chaque livre. Le résultat doit être :

<resultat>
<livre titre="Data on the Web">
<section id="intro" difficulty="easy">
Lettres initiales du Prénom et du Nom: page 13

<title>Introduction</title>
</section>
<section id="syntax" difficulty="medium">
<title>A Syntax For Data</title>
</section>
</livre>
</resultat>

1 point

<resultat>{
for $b in doc("book.xml")/book
return
<livre titre="{$b/title/text()}">
{
Lettres initiales du Prénom et du Nom: page 14

for $section in $b/section


return
<section>
{ $section/@* , $section/title }
</section>
}

</livre>
}
</resultat>
2 .Liste des figures avec leur titre et leurs attributs et avec, pour chaque figure, la section où elle apparaît
Le résultat doit être :

<liste_figures>
<figure section="Web Data and the Two Cultures" height="400" width="400">
<title>Traditional client/server architecture</title>
</figure>
<figure section="A Syntax For Data" height="200" width="500">
<title>Graph representations of structures</title>
</figure>
<figure section="Representing Relational Databases" height="250" width="400">
<title>Examples of Relations</title>
</figure>
</liste_figures>
Lettres initiales du Prénom et du Nom: page 15

1 point

<liste_figures>
{
for $f in doc("book.xml")//figure
return
<figure section="{$f/../title}">
{ $f/@* }
{ $f/title }
</figure>
}
</liste_figures>

3. Nombre de section pour chaque niveau et total.


Le résultat doit être :

<resultat>
<nb_sections_niveau1>2</nb_sections_niveau1>
<nb_sections_niveau2>5</nb_sections_niveau2>
<nb_sections_total>7</nb_sections_total>
</resultat>

1 point

<resultat>
<nb_sections_niveau1>
{
count(doc("book.xml")/book/section)
}
</nb_sections_niveau1>
<nb_sections_niveau2>
{
count(doc("book.xml")/book/section/section)
}
</nb_sections_niveau2>
<nb_sections_total>
Lettres initiales du Prénom et du Nom: page 16

{
count(doc("book.xml")//section)
}
</nb_sections_total>
</resultat>

4. Pour chaque section de niveau 1, donner la hauteur moyenne des figures et la liste des figures dont la
hauteur est supérieure ou égale à cette moyenne. La liste des sections doit apparaître dans l’ordre
croissante de la hauteur moyenne.
On obtient le résultat suivant :

<resultat>
<section title="A Syntax For Data" hauteurmoy="225">
<figure_haute title="Examples of Relations" hauteur="250"/>
</section>
<section title="Introduction" hauteurmoy="400">
<figure_haute title="Traditional client/server architecture" hauteur="400"/>
</section>
</resultat>

1 point

resultat>
{
Lettres initiales du Prénom et du Nom: page 17

for $s in doc("book.xml")/book/section
let $hm := avg($s//figure/@height)
order by $hm
return
<section title="{ $s/title/text() }" hauteurmoy="{ $hm }">
{for $f in $s//figure[@height>=$hm]
return
<figure_haute title="{ $f/title/text() }" hauteur="{$f/@height}"/>
}
</section>
}
</resultat>
5. Pour chaque livre, donner la liste des auteurs sous forme d’attribut de type string, et, pour chaque
section (niveau 2 imbriqué dans niveau 1), donner la taille (surface) occupée par la section, calculée à
partir de ses éléments. La taille d’un élément <p> vaut 3000, tout comme la taille d’un élément <title>. La
taille d’une figure est donnée par ses dimensions.
On obtient le résultat suivant :
<resultat>
<livre titre="Data on the Web" auteurs="Serge Abiteboul Peter Buneman Dan Suciu">
<section_niv1 titre="Introduction" taille="184000">
<section_niv2 titre="Audience" taille="6000"/>
<section_niv2 titre="Web Data and the Two Cultures" taille="172000"/>
</section_niv1>
<section_niv1 titre="A Syntax For Data" taille="233000">
<section_niv2 titre="Base Types" taille="6000"/>
<section_niv2 titre="Representing Relational Databases" taille="109000"/>
<section_niv2 titre="Representing Object Databases" taille="6000"/>
</section_niv1>
</livre>
</resultat>
Lettres initiales du Prénom et du Nom: page 18

1 point

<resultat>
{
for $b in doc("book.xml")/book
return
<livre titre="{$b/title}" auteurs="{$b/author/text()}">

{for $s in $b/section
let $taille := sum($s//figure/(@height * @width))
let $taille2 := 3000*count($s//(p|title))
return
<section_niv1 titre="{$s/title}" taille="{$taille+$taille2}" >
{for $ss in $s/section
let $sstaille := sum($ss//figure/(@height * @width))
let $sstaille2 := 3000*count($ss//(p|title))
return
<section_niv2 titre="{$ss/title}" taille="{$sstaille+$sstaille2}" />
}
</section_niv1>
}
</livre>
}
</resultat>
Nom : Prénom : page 1

Module Bases de Données et Web


Examen du 25 janvier 2007
Version CORRIGEE

Les documents sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. La taille des cadres suggère celle de la réponse
attendue. Utiliser le dos de la feuille précédente si la réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité
de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet.

Exercice 1 : DTD et XSchema 6 pts


Question 1. Complétez la DTD ci-dessous décrivant cette application. Les associations sont représentées par des
attributs.
1. <?xml version ="1.0" encoding="ISO-8859-1" ?>
2. < !ELEMENT Planification ……………..

3. < !ELEMENT Machine …………….

4. < !ATTLIST Machine ………………

5. < !ELEMENT Tache ……………

6. < !ATTLIST Tache ………………

< ?xml version ="1.0" encoding="ISO-8859-1" ?>


< !ELEMENT Planification((Machine)+|(Tache)*)>
< !ELEMENT Machine EMPTY>
< !ATTLIST Machine numero ID #REQUIRED
Description CDATA #IMPLIED
Realise IDREFS #IMPLIED>
< !ELEMENT Machine EMPTY>
< !ATTLIST Tache numero ID #REQUIRED
Duree CDATA #IMPLIED
Est-realisee-par IDREF #REQUIRED
précède IDREFS #IMPLIED
est-précédée-par IDREFS #IMPLIED>

Question 2. Pour chacune des contraintes suivantes, indiquez la ligne à modifier et les modifications à faire pour
exprimer la contrainte (si c’est possible).
a) Le système comprend au maximum deux machines
Lettres initiales du Prénom et du Nom: page 2

Ligne à modifier :
Modifications :
Ligne à modifier : 2
Modif : < !ELEMENT Planification(Machine|(Machine ?)|(Tache)*)>
b) Le numéro d’une tâche est un entier dans l’intervalle [1, 100]
Ligne à modifier :
Modifications :
Pas possible, ou alors énumérer toutes les valeurs (ce qui devient problématique à partir d’une certaine
taille)
c) Une tâche est réalisée par une et une seule machine
Ligne à modifier :
Modifications :

Ligne à modifier : 6
Modif : Est-realisee-par IDREF #REQUIRED (IDREF doit être au singulier + required)
d) Le numéro d’une machine est unique et obligatoire
Ligne à modifier :
Modifications :
Ligne à modifier : 4
Modif : < !ATTLIST Machine numero ID #REQUIRED
e) Le champ description d’une machine est une chaîne de caractères de longueur 50.
Ligne à modifier :
Modifications :
Modif : pas possible
f) Une tâche précède une ou plusieurs tâches
Ligne à modifier :
Modifications :
Ligne à modifier : 6
Modif : précède IDREFS #REQUIRED (Mettre IDREFS au pluriel et required)
Question 3. On souhaite maintenant modéliser cette application en XSchema.
3.1 Définir en Xschema, l’élément machine.
<xs:element name="machine"……
<xs:element name="machine">
<xs:complexType>
<xs:attribute name="numero" type="xs:integer" use="required"/>
<xs:attribute name="description" type="xs:string" use="optional"/>
<xs:attribute name="realise" type="xs:integer" use="optional"/>
Lettres initiales du Prénom et du Nom: page 3

</xs:complexType>
</xs:element>

3.2 Définir en Xschema, l’élément tache.


<xs:element name="tache"…………………………

<xs:element name="tache"/>
<xs:complexType>
<xs:attribute name="numero" type="xs:integer" use="required"/>
<xs:attribute name="duree" type="xs:integer" use="optional"/>
<xs:attribute name="precede" type="xs:integer" use="optional"/>
<xs:attribute name="est-realisee-par" type="xs:integer" use="required"/>
<xs:attribute name="est-precedee-par" type="xs:integer" use="optional"/>
</xs:complexType>
</xs:element>
3.3. En utilisant ces deux définitions, complétez la description du schéma ci-dessous. Pour la lisibilité de
la suite, pensez à numéroter les lignes.
1.<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.planification.org"
xmlns= "http://www.planification.org"
elementFormDefault="qualified">………………….
2.<xs:element name= "planification" ……………

3. <xs:complexType ………….

4. <xs:…………………….

5..

< /xs:complexType>
</xs:schema>

1. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.planification.org"
xmlns= "http://www.planification.org"
elementFormDefault="qualified">

2. <xs:element name= "planification" >


3. <xs:complexType >
4. <xs:choice…minOccurs="0" maxOccurs="unbounded">
5. <xs:element ref="machine" />
6. <xs:element ref="tache"/>
7. </xs:choice>
8. < /xs:complexType>

</xs:schema>

Question 4. Exprimez chacune des contraintes suivantes, en indiquant, s’il y a lieu, ce qu’il faut modifier,
et le numéro de ligne où insérer la contrainte.
a) Le système comprend au maximum deux machines
Modifications :
Lettres initiales du Prénom et du Nom: page 4

Contrainte :
Ligne où insérer la contrainte :
Ligne à modifier : 5
Modif : <xs:element ref="machine" minOccurs="0" maxOccurs="2"/>
b) Le numéro d’une tâche est un entier dans l’intervalle [1, 100]
Modifications :
Contrainte :
Ligne où insérer la contrainte :
Ligne à modifier : 10
Modif :
<xs:attribute name="numero" use="required">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>

c) L’attribut numéro est un identifiant unique pour les éléments machine et tache.
Modifications :
Contrainte :
Ligne où insérer la contrainte :
<xs:key name="cléMachine">
<xs:selector xpath="machine">
<xs:field xpath="@numero">
</xs:key>

xs:key name="cléTache">
<xs:selector xpath="tache">
<xs:field xpath="@numero">
d) Une tâche est réalisée par une et une seule machine
Modifications :
Contrainte :
Ligne où insérer la contrainte :
Plusieurs solutions : mettre type = IDREF use=required
On peut aussi modifier la ligne 10. Supprimer l’attribut Est-réalisé par et mettre :
10.<xs:element name="tache"/>
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name=est-realisé-par type=xs:integer/>
</xs:sequence>
<xs:attribute name="numero" type="xs:integer" use="required"/>
<xs:attribute name="duree" type="xs:integer" use="optional"/>
<xs:attribute name="precede" type="xs:integer" use="optional"/>
<xs:attribute name="est-precedee-par" type="xs:integer" use="optional"/>
</xs:complexType>
</xs:element>
Lettres initiales du Prénom et du Nom: page 5

e) Le champ description d’une machine est une chaîne de caractères de longueur 50.
Modifications :
Contrainte:
Ligne où insérer la contrainte :
Ligne à modifier : élément machine
Modif :
<xs:attribute name="description" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="50"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>

f) Une tâche précède une ou plusieurs tâches


Contrainte :
Ligne où insérer la contrainte :
Ligne à insérer : après les clefs
Modif : <xs:keyref name="précède" refer="cleTache">
<xs:selector xpath="tache">
<xs:field xpath="@précède" >
</xs:keyref>
Question 5. On souhaite maintenant distinguer les tâches initiales des autres tâches. Une tâche initiale
n’est précédée d’aucune autre tâche.
a) Définir le type TypeTacheInitiale

<xs:complexType name="TypeTacheInitiale">
<xs:attribute name="numero" type="xs:integer" use="required"/>
<xs:attribute name="duree" type="xs:integer" use="optional"/>
<xs:attribute name="precede" type="xs:integer" use="optional"/>
<xs:attribute name="est-realisee-par" type="xs:integer" use="required"/>
</xs:complexType>

b) définir le type TypeTache, en utilisant le type TypeTacheInitiale.

<xs:complexType name="TypeTache" >


<xs:complexContent>
<xs:extension base="TypeTacheInitiale">
<xs:attribute name="est-precedee-par" type="xs:integer" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Lettres initiales du Prénom et du Nom: page 6

Exercice 2 : ODMG et OQL 3 pts


L'application qu'on souhaite modéliser concerne une étude sur la consommation et la vente de bières dans les
différentes villes de France. Dans ce but, on souhaite représenter et gérer les données concernant les bières et les
activités liées à leur consommation et à leur vente dans divers établissements.

Une ville est désignée par un nom (identifiant), un certain nombre d'habitants, et peut contenir plusieurs
établissements de bières. Chaque établissement est désigné par un nom (identifiant), un horaire d'ouverture, un
numéro de téléphone, et propose une sélection de bières. On distingue deux types d'établissements: les magasins, et
les bars.

- Les magasins proposent des bières à l'achat, et sont caractérisés par une surface.

- Les bars proposent des bières à la consommation (sur place), et disposent d'une certaine capacité d'accueil.

Chaque bière est identifiée par une marque et un type, et est caractérisée par un prix, un fabriquant, un pays de
fabrication, et est consommée par un certain nombre de consommateurs. Un consommateur est caractérisé par un id
(identifiant), un nom, un numéro de téléphone, un âge, une ville de résidence, et peut consommer une variété de
bières en les achetant dans différents magasins ou en les consommant sur place dans différents bars.

Question 1. Compléter le diagramme du schéma de cette application en utilisant la représentation graphique de la


norme ODMG. Déterminer les racines de persistance correspondantes.

nom horaire
Racine de
Persistance
Établissements
Établissement

est_un

capacité

Bar
est_fréquenté_par

Consommateurs

Consommateur
fréquente

nom tél
Id_cons
Lettres initiales du Prénom et du Nom: page 7

Réponse : nbr_habitants
nom nom horaire
Racine de
Villes Persistance
est_situé_dans Établissements
Ville Établissement
contient
a_comme_résident propose

est_un est_un
marque
surface proposée_par capacité
type
Magasin Bière
Bar
a_comme_client consomme
Bières fabriquant fréquenté_par

pays
Consommateurs

consommée_par
client_de
Consommateur
fréquente
réside_dans

Id_cons nom téléphone âge

La définition ODL du sous-schéma de la Question 1 étant la suivante:

interface Établissement // extent définit une racine de persistance


(extent Établissements key nom)
{ attribute string nom;
attribute string horaire;
boolean est_un_Bar(); // cette méthode renvoie vrai si l'objet cible sur lequel elle
// est invoquée est de type Bar, et faux autrement.
}

interface Bar : Établissement // " : " définit le lien d'héritage entre Bar et Établissement
{ attribute integer capacité;
relationship set<Consommateur> est_fréquenté_par
inverse Consommateur::fréquente;
}

interface Consommateur
(extent Consommateurs key Id)
{ attribute string Id;
attribute string nom;
attribute string adresse;
attribute string tél;
attribute integer âge;
relationship set<Bar> fréquente
inverse Bar::est_fréquenté_par;
}

Question 2. Exprimer en OQL les requêtes suivantes sur ce sous-schéma :


R1. Trouver le nom des bars ayant plus de 100 clients (consommateurs) de moins de 25 ans.
Lettres initiales du Prénom et du Nom: page 8

Réponse:

SELECT E.nom
FROM E
IN Etablissements
WHERE E → est_un_Bar() AND COUNT (SELECT C
FROM C
IN E.fréquenté_par
WHERE C.âge < 25) > 100;

R2. Trouver le nom des bars dont tous les clients (consommateurs) ont moins de 25 ans.

Réponse:

1. SELECT STRUCT (Nom: E.nom,


Moyenne_Age: AVG (SELECT C.âge
FROM C
IN E.fréquenté_par))
FROM E
Lettres initiales du Prénom et du Nom: page 9

IN Etablissements
WHERE E → est_un_Bar() AND NOT EXISTS C IN E.est_fréquenté : C.âge >= 25;

Rem: l'utilisation du STRUCT n'est oas obligatoire…

Exercice 3 : SQL3 4 pts


Soit le schéma entité-association suivant:

Bar Consommateur
nom Id_cons
tél 1:n 1:1
fréquente nom
horaire tél
capacité âge

1:n
consomme

consommée_par
1:n
Bière
marque
type
fabriquant
pays
prix

Question 1. Traduire en SQL3 le schéma entité-association ci-dessus en implémentant les associations dans le sens
désigné par les flèches noires.

Compléter les instructions suivantes :


CREATE TYPE Bar AS OBJECT(
nom VARCHAR(20),
téléphone VARCHAR(10),
horaire VARCHAR(115),
capacité NUMBER(4)
);
Lettres initiales du Prénom et du Nom: page 10
Lettres initiales du Prénom et du Nom: page 11

CREATE TYPE Bar AS OBJECT(


nom VARCHAR(20),
téléphone VARCHAR(10),
horaire VARCHAR(115), //hh:mn – hh:mn
capacité NUMBER(4)
);

CREATE TYPE Bière;

CREATE TYPE obj_Bière AS OBJECT(


ptr REF Bière;
);

CREATE TYPE EnsBière AS TABLE OF obj_Bière;

CREATE TYPE Consommateur AS OBJECT(


Id_cons VARCHAR(10),
nom VARCHAR(20),
téléphone VARCHAR(10),
âge NUMBER(3),
fréquente REF Bar,
consomme EnsBière
);
Lettres initiales du Prénom et du Nom: page 12

CREATE TYPE obj_Cons AS OBJECT(


ptr REF Consommateur;
);

CREATE TYPE EnsCons AS TABLE OF obj_Cons;

CREATE TYPE Bière AS OBJECT(


Marque VARCHAR(10),
Type VARCHAR(10),
Fabriquant VARCHAR(10),
Pays VARCHAR(10),
Prix NUMBER(4,2),
consommé_par EnsCons
);

Question 2. Créer les tables nécessaires au stockage des objets Bar, Bière, et consommateur.

Compléter les instructions suivantes :

CREATE TABLE LesBars OF Bars;

CREATE TABLE LesBars OF Bars ;

CREATE TABLE LesBières OF Bière


NESTED TABLE consommé_par STORE AS table_consommé_par ;

CREATE TABLE LesConsommateurs OF consommateur


Lettres initiales du Prénom et du Nom: page 13

NESTED TABLE consomme STORE AS table_consomme ;

Question 3. Ecrire les requêtes suivantes en SQL3

R1. Trouver le nom des bars ayant plus de 100 clients (consommateurs) de moins de 25 ans.

Select C.fréquente.nom
From LesConsommateurs C
Where C.âge < 25
Group by C.fréquente
Having count(*) >= 100;

R2. Trouver le nom des consommateurs qui ont consommé au moins une fois la bière de la marque Chimay.

Réponse:
Select C.nom
From LesConsommateurs C, table (C.consomme) B
Where B.ptr.marque = "Chimay";
Lettres initiales du Prénom et du Nom: page 14

Exercice 4 : XPath et XQuery 7 pts

Soit le fichier XML family.xml suivant :


<?xml version="1.0" encoding="UTF-8"?> <personne id = "p8" genre = "m">
<base> <prenom>Louis</prenom>
<personne id = "p1" genre = "m"> <nom>Daile</nom>
<prenom>Pierre</prenom> <age>6</age>
<nom>Rao</nom> <pere idref = "p3"/>
<age>58</age> <mere idref = "p4"/>
<conjoint idref = "p2"/> </personne>
</personne>
<personne id = "p9" genre = "f">
<personne id = "p2" genre = "f"> <prenom>Marie</prenom>
<prenom>Isabelle</prenom> <nom>Daile</nom>
<nom>Rao</nom> <age>5</age>
<age>61</age> <pere idref = "p3"/>
<conjoint idref = "p1"/> <mere idref = "p4"/>
</personne> </personne>

<personne id = "p3" genre = "m"> <famille id = "f1">


<prenom>Fernand</prenom> <epoux idref = "p1"/>
<nom>Daile</nom> <epouse idref = "p2"/>
<age>32</age> <mariage>
<conjoint idref = "p4"/> <lieu>Bandol</lieu>
</personne> <date>12 fevrier 1975</date>
</mariage>
<personne id = "p4" genre = "f"> </famille>
<prenom>Fernande</prenom>
<nom>Ehle</nom> <famille id = "f2">
<age>27</age> <epoux idref = "p3"/>
<conjoint idref = "p3"/> <epouse idref = "p4"/>
<pere idref = "p1"/> <mariage>
<mere idref = "p2"/> <lieu>Lyon</lieu>
</personne> <date>12 mars 1999</date>
</mariage>
<personne id = "p5" genre = "f"> </famille>
<prenom>Elise</prenom>
<nom>Lettra</nom> <famille id = "f3">
<age>27</age> <epoux idref = "p7"/>
<conjoint idref = "p7"/> <epouse idref = "p5"/>
<pere idref = "p1"/> <mariage>
<mere idref = "p2"/> <lieu>Toulouse</lieu>
</personne> <date>3 avril 2001</date>
</mariage>
<personne id = "p6" genre = "f"> </famille>
<prenom>Lucie</prenom>
<nom>Daile</nom> </base>
<age>6</age>
Lettres initiales du Prénom et du Nom: page 15

<pere idref = "p3"/>


<mere idref = "p4"/>
</personne>

<personne id = "p7" genre = "m">


<prenom>Jean</prenom>
<nom>Lettra</nom>
<age>30</age>
<conjoint idref = "p5"/>
</personne>

Question 1. Exprimez en XPath les requêtes suivantes :


1. Les petits-enfants de Pierre Rao. Résultat : les personnes d’id p6, p8, p9

0.75 point
//personne[pere/@idref=//personne[pere/@idref=//personne[nom='Rao'
and prenom='Pierre']/@id]/@id or mere/@idref=//personne[pere/@idref=//personne[nom='Rao'
and prenom='Pierre']/@id]/@id]
2. Nom des personnes dont le père s’est marié le 12 février 1975. Résultat : Ehle, Lettra.

0.75 point
//personne[//famille[mariage/date='12 fevrier 1975']/epoux/@idref=pere/@idref]
3. Prénom des célibataires. Résultat : Lucie, Louis, Marie.

0.75 point
//personne[not(conjoint)]/prenom
Lettres initiales du Prénom et du Nom: page 16

4. Ages des sœurs (mêmes père et mère) de Lucie Daile. Résultat : 5

0.75 point
//personne[pere/@idref=//personne[nom='Daile' and
prenom='Lucie']/pere/@idref and mere/@idref=//personne[nom='Daile' and
prenom='Lucie']/mere/@idref and @genre='f' and @id!=//personne[nom='Daile' and
prenom='Lucie']/@id]/age

Question 2. Ecrire en XQuery les requêtes suivantes :

1. Donner, lorsque c’est possible, la liste des hommes (nom et prénom) et la différence d’âge avec leur
père. Le résultat doit être :
<root>
<Personne>
<nom>Daile</nom>
<prenom>Louis</prenom>
<diff-age>26</diff-age>
</Personne>
</root>
Lettres initiales du Prénom et du Nom: page 17

1 point

<root>
{ for $p in document("family.xml")//personne[@genre='m']
let $nomp:=$p/nom
let $prenomp:=$p/prenom
let $pere:=document("family.xml")//personne[@id=$p/pere/@idref]
where exists($pere)
return
<Personne>
{$nomp}
{$prenomp}
<diff-age>
{$pere/age - $p/age}
</diff-age>
</Personne>}
</root>
2 .Donner la liste des hommes (nom et prénom), avec, s’il existe, le prénom du père.
Le résultat doit être :
<root>
<Personne><nom>Rao</nom><prenom>Pierre</prenom></Personne>
<Personne><nom>Daile</nom><prenom>Fernand</prenom></Personne>
<Personne><nom>Lettra</nom><prenom>Jean</prenom></Personne>
<Personne>
<nom>Daile</nom>
Lettres initiales du Prénom et du Nom: page 18

<prenom>Louis</prenom>
<prenompere>Fernand</prenompere>
</Personne>
</root>

1 point

<root>
{ for $p in document("family.xml")//personne[@genre='m']
let $nomp:=$p/nom
let $prenomp:=$p/prenom
let $pere:=document("family.xml")//personne[@id=$p/pere/@idref]
return
<Personne>
{$nomp}
{$prenomp}
{if ($pere) then
<prenompere>
{$pere/prenom/text()}
</prenompere>
else () }
</Personne>}
</root>
4. Donner la moyenne d’âge des gendres (maris des filles) de Pierre Rao.
On obtient le résultat suivant : <root>31</root>
Lettres initiales du Prénom et du Nom: page 19

1 point

<root>
{ let $pr:=document("family.xml")//personne[nom='Rao' and prenom='Pierre']
let $fpr:=document("family.xml")//personne[pere/@idref=$pr/@id and @genre='f']
let $gpr:=document("family.xml")//personne[conjoint/@idref=$fpr/@id and @genre='m']
return avg($gpr/age)
}
</root>
Nom : Prénom : page 1

Module Bases de Données et Web


Examen du 21 décembre 2006
Version CORRIGEE

Les documents sont autorisés – Durée : 2h.


Répondre aux questions sur la feuille du sujet dans les cadres appropriés. La taille des cadres suggère celle de la réponse
attendue. Utiliser le dos de la feuille précédente si la réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité
de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet.

Exercice 1 : Questions diverses 2 pts


Question 1
Enumérer au moins deux avantages de la répartition d'une base de données sur plusieurs sites.
Question 2
Enumérer deux limites du modèle DTD par rapport au modèle XSchéma.
Question 3
Enumérer deux avantages d'un SGBD orienté objet par rapport à un langage de programmation orienté
objet.
Question 4
Enumérer deux avantages du modèle XML par rapport aux modèles de données classiques, tels que le
relationnel ou l'orienté objet.

Exercice 2 : BD réparties 4 pts


La base de données d'un institut de recherche en Biologie a le schéma global suivant:

LABORATOIRE (codeL, nom, sigle, région, adresse, directeur)


CHERCHEUR (#chercheur, codeL, nom, prénom, spécialité, salaire, prime)
PROJET (codeP, codeL, titre, chef, budget, durée, date_début)
PARTICIPE (#chercheur, codeP, rôle, taux_participation)

L'institut est formé de trois centres de recherche situés dans trois régions Françaises : Paris, Lille, et
Grenoble. Chaque centre est formé de plusieurs laboratoires. En supposant que la base de données de
l'institut est répartie sur trois sites informatiques correspondant aux centres de Paris, de Lille, et de
Grenoble, proposer une bonne décomposition de la base sur ces trois sites en se basant sur les hypothèses
suivantes.
- Chaque centre gère ses propres données.
- L'attribut région de LABORATOIRE prend une des valeurs suivantes: "Paris", "Lille", "Grenoble".
- L'attribut spécialité de CHERCHEUR prend une des valeurs suivantes : "Virologie", "Parasitologie",
"Neuroscience", "Microbiologie", "Epidémiologie", "Génétique", " Immunologie".
- codeL (resp. #chercheur, codeP) est clé primaire de LABORATOIRE (resp. CHERCHEUR, PROJET).
- Le chef d'un projet et le directeur d'un laboratoire sont des chercheurs désignés par leurs numéros.
- Chaque chercheur est rattaché à un laboratoire donné, et peut participer à plusieurs projets de son
laboratoire.

Question 1
Lettres initiales du Prénom et du Nom: page 2

Donner la définition des différents fragments en utilisant les opérateurs de l’algèbre relationnelle.
Réponse:

i ∈ {Paris, Lille, Grenoble}


Pi ∈ {(région = ‘Paris), (région = ‘Lille), (région = ‘Grenoble’)}
LABORATOIREi = σPi (LABORATOIRE)
CHERCHEURi = CHERCHEUR LABORATOIREi
PROJETi = PROJET LABORATOIREi
PARTICIPEi = PARTICIPE PROJETi

Question 2
Dans cette question, le centre de la région Parisienne tient également lieu de siège pour l'institut. Afin de
séparer les données scientifiques des données administratives, supposons maintenant que la relation
CHERCHEUR est répartie sur les trois sites informatiques de Paris, de Lille, et de Grenoble comme suit:

i ∈ {Paris, Lille, Grenoble}


Pi ∈ {(région = ‘Paris), (région = ‘Lille’), (région = ‘Grenoble’)}

π#chercheur, codeL, nom, prénom, spécialité (σPi (CHERCHEUR))


CHERCHEUR_SCi =

CHERCHEUR_ADMINParis = π#chercheur, nom, prénom, salaire, prime (CHERCHEUR)


CHERCHEUR_ADMINLille = CHERCHEUR_ADMINGrenoble = ∅

Proposez un plan d'exécution réparti de la requête permettant de retrouver, pour chaque laboratoire, le
revenu le plus élevé (salaire + prime) d'un chef de projet du laboratoire. On suppose que la requête est
émise par le siège de l'institut. Le plan proposé doit optimiser le coût de communication inter sites.
Réponse:
Soit R1 la sous-requête suivante:
SELECT #chercheur, C.codeL
FROM CHERCHEUR_SC C, PROJET P
WHERE #chercheur = chef;

-- Le site SParis execute:


SEND R1 TO Si; // i ∈ {Paris, Lille, Grenoble}

-- Les sites Si exécutent:


RECEIVE R1 FROM SParis;
(R1) → Ti;
SEND Ti TO SParis;

-- Le site SParis execute:


RECEIVE Ti FROM Si;

( SELECT *
FROM TParis ) UNION
( SELECT *
Lettres initiales du Prénom et du Nom: page 3

FROM TLille ) UNION


( SELECT *
FROM TGrenoble ) → Temp

SELECT T.codeL, Max(salaire + prime)


FROM CHERCHEUR_ADMIN CA, Temp T
WHERE CA.#chercheur = T.#chercheur
GROUP BY T.codeL;

Exercice 3 : DTD et XMLSchema 6 pts

L’objectif de cet exercice est d’étudier les fichiers XMLSchema.dtd et XMLSchema.xsd, qui décrivent les
éléments de XMLSchema.

Question 1. (2pts)
On demande d’écrire la DTD des éléments xs:key et xs :keyref de XMLSchema.
On pourra utiliser l’entité %XPathExpr ; , qui décrit l’ensemble des expressions XPath, pour définir les
expressions XPath. On suppose cette entité déjà définie.

Réponse :

<!ELEMENT xs:key (xs:selector, (xs:field)+)>


<!ATTLIST xs:key
name ID #REQUIRED>

<!ELEMENT xs:keyref (xs:selector, (xs:field)+)>


<!ATTLIST xs:keyref
name CDATA #REQUIRED
refer IDREF #REQUIRED>

<!ELEMENT xs:selector >


<!ATTLIST xs:selector
xpath %XPathExpr; #REQUIRED>

<!ELEMENT xs:field >


<!ATTLIST xs:field
xpath %XPathExpr; #REQUIRED>

Question2 (2pts)
Soit la DTD suivante, décrivant l’élément xs :attribute de XMLSchema.

<!ELEMENT xs:attribute ((xs:simpleType)?)>


<!ATTLIST xs:attribute
name CDATA #IMPLIED
id ID #IMPLIED
type CDATA #IMPLIED
use (prohibited|optional|required) #IMPLIED
default CDATA #IMPLIED
fixed CDATA #IMPLIED>
Lettres initiales du Prénom et du Nom: page 4

On demande d’écrire la définition de cet élément xs:attribute en XMLSchema, en définissant le type


TypeAttribute indépendamment.

On suppose que l’élément simpleType est de type TypeSimpleType

Réponse :
<xs:complexType name="TypeAttribute">
<xs:complexContent>
<xs:sequence>
<xs:element name="simpleType" minOccurs="0" type="xs:localSimpleType"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string"/>
<xs:attribute name="use" use="optional" default="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="prohibited"/>
<xs:enumeration value="optional"/>
<xs:enumeration value="required"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="default" type="xs:string"/>
<xs:attribute name="fixed" type="xs:string"/>
</xs:complexContent>
</xs:complexType>

<xs :element name= "attribute" type="TypeAttribute">


Question 3 (1pt)
Quelles contraintes, sur un schéma XMLSchema, impliquent les extraits suivants, du fichier
XMLSchema.xsd ?
1)
<xs:key name="type">
<xs:selector xpath="xs:complexType|xs:simpleType"/>
<xs:field xpath="@name"/>
</xs:key>
Réponse : unicité des noms de type (parmi l'ensemble des types complexes et simples non anonymes)
2)
<xs:key name="identityConstraint">
<xs:selector xpath=".//xs:key|.//xs:unique|.//xs:keyref"/>
<xs:field xpath="@name"/>
</xs:key>
Réponse : unicité des noms de contraintes

Question 4. (1 pt)
Lettres initiales du Prénom et du Nom: page 5

Dans la définition de l’élément xs:element, les noms d’éléments utilisés comme valeur de l’attribut ref
doivent mentionner des éléments existants (c’est-à-dire la valeur de l’attribut name d’un autre élément
existant).
On demande de définir cette contrainte à l’aide de keyref, en se basant sur la contrainte de clé appelée
"element" définie ci dessous:

<xs:key name="element">
<xs:selector xpath="xs:element"/>
<xs:field xpath="@name"/>
</xs:key>

Réponse :

<xs:keyref name=”RefConstraint” refer=”element”>


<xs:selector xpath=”xs:element”/>
<xs:field xpath=”@ref”/>

Exercice 4 : XPath et XQuery 8 pts

Soit le fichier XML Atlas.xml suivant :


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE atlas SYSTEM "atlas.dtd">
<atlas>
<pays n="p2" population="82" continent="c1">
<nom>Allemagne</nom>
<langue>Allemand</langue>
<frontiere pays="p1"/>
</pays>
<pays n="p1" population="60" continent="c1" >
<nom>France</nom>
<langue pourcentage="100">Français</langue>
<langue pourcentage="1">Corse</langue>
<frontiere pays="p2"/>
<frontiere pays="p3"/>
</pays>
<pays n="p3" population="40" continent="c1">
<nom>Espagne</nom>
Lettres initiales du Prénom et du Nom: page 6

<langue pourcentage="74">Espagnol</langue>
<langue pourcentage="17">Catalan</langue>
<langue pourcentage="7">Galicien</langue>
<frontiere pays="p1"/>
</pays>
<pays n="p4" population="76" continent="c2">
<nom>Egypte</nom>
<langue>Arabe</langue>
</pays>

<continent n="c1" nom="Europe" superficie="10"/>


<continent n="c2" nom="Afrique" superficie="30"/>

<mer n="m1" nom="Mer Mediterranee" profondeur="5120">


<situation pays="p1"/> <situation pays="p3"/> <situation pays="p4"/>
</mer>

<montagne n="M1" nom="Alpes" altitude="4810">


<situation pays="p1"/> <situation pays="p2"/>
</montagne>
<montagne n="M2" nom="Cevennes" altitude="1700">
<situation pays="p1"/>
</montagne>
</atlas>

Question 1. Exprimez en XPath les requêtes suivantes :


1. Langues qui ne sont pas parlées en Europe.

//pays[@continent=//continent[not(@nom=’europe’)]/langue
2. Nom des pays méditerranéens (ayant un accès à la mer Méditerranée)

//pays[@n=//mer[@nom=’Mer méditerrannée’]/situation/@pays
3. Nom des pays ayant des frontières avec plus de 3 autres pays.
Lettres initiales du Prénom et du Nom: page 7

//pays[count(frontiere)>3]/nom
4. Pays de plus de 40 millions d’habitants n’ayant pas de montagne de sommet supérieur à 2000.

//pays[@population>40][not(@n=//montagne[@altitude>2000]/situation/@pays)]

Autres questions éventuellement :


Langues des pays d’Europe parlées par moins de 40% de la population du pays.
//pays[@continent=//continent[@nom=’europe’]/langue[pourcentage<=40]

Question 2. Expliquer en une phrase en français ce que signifient les expressions XPath suivantes, et
donner le résultat de leur évaluation sur le document Atlas.xml.
1. //pays[population<80 and position()=2]/nom

Renvoie le 2eme élément pays s’il a une population inférieure à 80.


Renvoie France.
2. //pays[population<80][position()=2]/nom

Sélectionne tous les éléments pays qui ont une population inférieure à 80 et renvoie le 2eme.
Renvoie Espagne

Question 3. Ecrire en XQuery les requêtes suivantes :

1 . Donner les noms des pays qui sont voisins du pays d’identificateur p1 (n=’p1’).
Le résultat doit être :
<root>
Lettres initiales du Prénom et du Nom: page 8

<nom>Allemagne</nom>
<nom>Espagne</nom>
</root>

1 point
<root>
{ for $p in document("atlas.xml")//pays
where $p/frontiere/@pays='p1'
return $p/nom }
</root>

2. Donner les noms des pays dont toutes les langues sont parlées par au moins 2% de la population. Le
résultat doit être :
<root>
<nom>Espagne</nom>
</root>

1.25 point
<root>
{ for $p in document("atlas.xml")//pays
where every $l in $p/langue satisfies $l/@pourcentage > 2
return $p/nom
}
</root>

3. Donner, dans l’ordre alphabétique, tous les noms de continent, suivi chacun par les noms des pays
composant le continent, dans l’ordre alphabétique également. On obtient une hiérarchie à trois niveaux
suivante :
<monde>
<continent nom="Afrique">
<pays>Egypte</pays>
</continent>
<continent nom="Europe">
<pays>Allemagne</pays>
<pays>Espagne</pays>
<pays>France</pays>
</continent>
Lettres initiales du Prénom et du Nom: page 9

</monde>

1.25 point

<root>
{ for $c in document("atlas.xml")//continent
order by $c/@nom
return <continent>
{$c/@nom}
{ for $p in document("atlas.xml")//pays
where $p/@continent=$c/@n
order by $p/nom
return <pays> {$p/nom/text()} </pays>
}
</continent>
}
</root>

4. Donner tous les noms de montagne, suivi chacun par les noms des pays dans lesquels est située la
montagne. On obtient le résultat suivant :
<root>
<montagne nom="Alpes">
<pays>Allemagne</pays>
<pays>France</pays>
</montagne>
<montagne nom="Cévennes">
<pays>France</pays>
</montagne>
</root>

1.25 point

<root>
{ for $m in document("atlas.xml")//montagne
return <montagne>
{$m/@nom}
{ for $p in document("atlas.xml")//pays,
Lettres initiales du Prénom et du Nom: page 10

$s in $m/situation
where $s/@pays=$p/@n
return <pays> {$p/nom/text()} </pays>
}
</montagne>
}
</root>

5. Donner la population totale, pour le fichier Atlas.xml, de chaque continent.


Le résultat doit être :
<root>
<continent nom="Europe">182</continent>
<continent nom="Afrique">76</continent>
</root>

1.25 point

<root>
{ for $c in document("atlas.xml")//continent
let $pops := document("atlas.xml")//pays[@continent=$c/@n]
return <continent>
{$c/@nom}
{count($pops/@population)}
}
</continent>
}
</root>
Nom : Prénom : page 1

Université Pierre et Marie Curie - Paris 6 - UFR 922 - Maîtrise d'informatique

Module Bases de Données et Web


Partiel du 8 novembre 2006
Les documents ne sont pas autorisés – Durée : 2h.
Répondre aux questions sur la feuille du sujet dans les cadres appropriés. La taille des cadres suggère celle de la réponse
attendue. Utiliser le dos de la feuille précédente si la réponse déborde du cadre. Le barème est donné à titre indicatif. La qualité
de la rédaction sera prise en compte. Ecrire à l’encre bleue ou noire. Ne pas dégrafer le sujet.

Exercice 1 : Questions de cours 2 pts


Question 1. Décrivez brièvement les différentes étapes de l’optimisation des requêtes.

1. ………..…

2………….…

3…………….

4…………….


Question 2.
a) Décrire au moins deux inconvénients du hachage statique par rapport au hachage dynamique.

Inconvénient 1:

Inconvénient 2:

b) Décrire un avantage et un inconvénient du hachage dynamique par rapport aux arbres B+.

Avantage:
Lettres initiales du Prénom et du Nom: page 2

Inconvénient:

Exercice 2 : Méthodes de placement et d'accès 4 pts


Question 1. On considère l'arbre B+ suivant d'ordre 1, i.e., les nœuds peuvent contenir au plus 2 clés et
au moins 1 clé. Montrer l'arbre B+ résultant de :
a) l'insertion de la clé 31;
b) l'insertion de la clé 27;
c) la suppression de la clé 29;
d) l'insertion de la clé 26;
e) l'insertion de la clé 17 ;
f) la suppression de la clé 13;
Pour simplifier, on ne considère pas la redistribution de clés.

25 29

13 15 25 29 33
Lettres initiales du Prénom et du Nom: page 3

26
29
26
26
25
25 31
31
15 2525 31 31
25 31
13 15 25 27 29 31 33
15 17 25 26 27 31 33
13 25 2725
13 15 15 17 26 33
31 27 31 33
13 15 25 26 27 31 33
25 31

13 15 25 29 31 33
Lettres initiales du Prénom et du Nom: page 4

Question 2.
Soit un fichier contenant des descriptions de produits selon le schéma relationnel suivant :
PRODUIT (NumP, NomP, TypeP, Qté, Prix)
Le fichier est placé sur disque par hachage statique multi-attributs sur les attributs NumP, NomP, et
TypeP. Le hachage permet de générer pour chaque tuple le numéro du paquet où le tuple sera stocké. On
suppose que la taille d'un paquet est celle d'un bloc disque. Le numéro des paquets est composé de
résultant de l'application d'une fonction de hachage à NumP, p2 bits résultant de l'application d'une
fonction de hachage à NomP, et p3 bits à TypeP, i.e.,
h1(NumP)  b11b12b13…b1p1
h2 (NomP)  b21b22b23…b2p2 => N°Paquet(tuple) = < b11b12b13…b1p1 / b21b22b23…b2p2 / b31b32b33…b3p3>
h3 (TypeP)  b31b32b33…b3p3
P1 bits P2 bits P3 bits

a) Calculer le nombre d'E/S à effectuer pour exécuter les requêtes suivantes :


1. recherche des produits tels que NumP = 100;
2. recherche des produits tels que NomP = 'Calculateur' et TypeP = 'T1'
3. recherche des produits tels que NomP = 'Calculateur' ou TypeP = 'T1'
4. insertion du produit (100, 'Calculateur', 'T1', 20, 15000)

NomP = 'Calculateur', et p3 bits sont fixés pour avoir les tuples tels que TypeP = 'T1'. Pour avoir tous les
tuples qui satisfont l'une OU l'autre des conditions => + b) Sachant que les fréquences d'interrogation
sur chaque attribut NumP, NomP, TypeP sont respectivement f1, f2, et f3, calculer le nombre de bits
optimal à allouer dans la composition du numéro de paquet pour NumP, NomP, et TypeP.
Lettres initiales du Prénom et du Nom: page 5

Exercice 3 : ODMG et OQL 4 pts


On considère le schéma ODMG suivant :

Classe Adresse {
Attribute number numero ;
Attribute string rue ;
Attribute string ville ;
}

Classe Personne (extent LesPersonnes) {


Attribute string nom ;
Attribute string prenom ;
Attribute string sexe ;
Attribute Adresse adr ;
Attribute list(string) activites ;
Relationship set(Personne) enfants inverse Personne :: parents ;
Relationship list(Personne) parents inverse Personne ::enfants ;
}

Question 1 (3pts). Ecrire en OQL les requêtes suivantes :

R1. Nom et prénom des personnes ayant des petits-enfants habitant Lyon.

R2. Enfants dont un des parents pratique le ski.


Lettres initiales du Prénom et du Nom: page 6

R3. Nom et prénom des enfants dont les parents n’habitent pas la même ville.

Question 2 (1pt). Parmi l’ensemble des activités, on souhaite distinguer les activités sportives, pour
lesquelles on indiquera la catégorie de la personne (poussin, benjamin, senior,…), et le jour de pratique
du sport. Modifier le schéma en conséquence.

Exercice 4 : Questions TME 2 pts

Question 1

On considère la relation SOURCE (OWNER, NAME, TYPE, LINE, TEXT), décrivant le code source de
tous les objets stockés d’un utilisateur.
Les attributs de la relation sont décrits ci-dessous :
OWNER VARCHAR2(30) : propriétaire de l’objet.
NAME VARCHAR2(30) : nom de l’objet
TYPE VARCHAR2(12) : type de l’objet (PROCEDURE, PACKAGE, FUNCTION, PACKAGE
BODY, TRIGGER, TYPE, TYPE BODY )

LINE NUMBER : numéro de la ligne du code source


TEXT VARCHAR2(4000) : texte source de l’objet
Lettres initiales du Prénom et du Nom: page 7

Question 1. Ecrire la procédure Affiche (nom, ligne1, ligne2) pour afficher le morceau de code source
(ligne1 à ligne2) de la procédure dont le nom est passé en paramètre.
Create or replace procedure Affiche ……….

Question2. Donnez l’instruction permettant d’exécuter la procédure qui affiche le code source de la
fonction F1 de la ligne 1 à la ligne 10.

Exercice 5 : SQL3 8 pts

On considère une base de données dont le schéma Entité/Association est donné ci-dessous :
Lettres initiales du Prénom et du Nom: page 8

:
marié_à
numéro : nom

prenom
rue
Maison Habite Personne
age
: :
:

: :
: enfant_de

Située Contient

: :

Ville Pièce

CodePostal Nom Type Taille

On précise qu’une personne habite une maison (résidence principale) et peut éventuellement avoir une
(seule) résidence secondaire. Il n’y a pas de maison non habitée, ni de ville sans habitant, ni de
polygamie.

Question 1 ( 0,5 points)

Compléter le schéma précédent en indiquant les cardinalités maximum:minimum dans les cadres prévus à
cet effet. On rappelle que les cardinalités s’expriment d’une entité vers une association, la flèche indique
le sens de lecture pour les associations réflexives.

Question 2 ( 0,5 points)

Quelle contrainte d’intégrité sur un ou des attribut(s) de Personne est induite par l’association
enfant_de ? Répondre par une phrase en français.
Lettres initiales du Prénom et du Nom: page 9

Question 3 ( 2 points)

Compléter la série d’instruction SQL3 suivante pour créer le schéma d’une telle base de données. Vous
ne pouvez pas créer de type supplémentaire ni de table supplémentaire.
CREATE TYPE Personne;
CREATE TYPE Piece AS OBJECT(
…………………………………
…………………………………
………………………………… );
CREATE TYPE Ville AS OBJECT(
nom VARCHAR2(50),
codePostal VARCHAR2(5) );

CREATE TYPE LesPieces AS ………………………………Piece;

CREATE TYPE Maison AS OBJECT(


numéro NUMBER(3),

rue VARCHAR2(30),

situé ……………………………………….,
contient ……………………………………. );

CREATE TYPE EnsMaisons AS ………………………………………………… Maison;

CREATE TYPE EnsParents AS ………………………………………………. Personne;

CREATE TYPE Personne AS OBJECT (


nom …………………………………………………,

prénom …………………………………………………,

age …………………………………………………,

habite …………………………………………………,
Lettres initiales du Prénom et du Nom: page 10

marié_à …………………………………………………,

enfant_de ………………………………………………… );

CREATE TABLE LesPersonnes OF ………………………..


………………………………………………………………..
……………………………………………………………….. ;

CREATE TABLE LesVilles OF ………………………..


………………………………………………………………..
……………………………………………………………….. ;

CREATE TABLE LesMaisons OF ………………………..


………………………………………………………………..
……………………………………………………………….. ;

Question 4 ( 5 points)

Soit le schéma objet-relationnel de la question précédente.

4.1) Insertion/mise à jour (2 Points)

• Insérer dans la base le bébé Jean Peuhplu qui vient de naître, fils de Claude Peuhplu et Martine
Hique, et qui habite 3 rue du Soleil à Paris, 20ème.
Lettres initiales du Prénom et du Nom: page 11

• Pour fêter l’heureux événement, les parents de Jean Peuhplu décide de se marier. Mettez la base à
jour en conséquence.
Lettres initiales du Prénom et du Nom: page 12

4.2) Requêtes (3 points)

Donner le code SQL des requêtes suivantes :

1) Dans quelle(s) ville(s) habite Edgar Dunord (donner le nom de la ville)


Lettres initiales du Prénom et du Nom: page 13

2) Donner le prénom des personnes qui habitent avec leur conjoint

3) Adresse (numéro, rue, code postal) des maisons de + de 5 pièces


Lettres initiales du Prénom et du Nom: page 14

4) Les couples (nom et prénom des deux conjoints)

Das könnte Ihnen auch gefallen