• Aucun résultat trouvé

FormatPowerPoint97

N/A
N/A
Protected

Academic year: 2022

Partager "FormatPowerPoint97"

Copied!
149
0
0

Texte intégral

(1)

7 Conception dans un contexte relationnel

Planification

Analyse

Conception

Spécification des besoins

Modèle conceptuel

Construction

Modèle physique

Mise en oeuvre

Schémas (LDD), modules codés et testés

Maintenance

Pourquoi ?

Quoi ?

Comment ?

(2)

Architecture

 Matériel

– centralisé, 2-tier, 3-tier, réparti, entrepôt de données,...

– plate-formes (parallélisme)

– réseau

 Logiciel

– couches

 Interface, Contrôle, Domaine, Persistance, Réseau,…

– partition par sous-domaine

– classes d ’implantation/modules

 Diagrammes de composantes UML

– répartition des composantes

 Diagrammes de déploiement UML

(3)

Réutilisation de composantes

 Interface à l ’utilisateur

– X-Windows, Windows, SWING...

 Communication

– TCP/IP, CORBA, RMI, DCOM, ...

 Persistance

– ODBC, JDBC, SGBD,...

(4)

Réalisation de la persistance

 Constantes du programme d ’application

 Fichiers (API du SGF)

 Librairies spécialisées

 SGBD

– souplesse, robustesse, intégrité,…

– approche privilégiée dans ce chapitre

 SGBD relationnel SQL centralisé

(5)

Forces du relationnel

 Accessibilité large

 Maturité de la technologie

 Fondements théoriques solides

 Standard répandu (SQL)

 Support solide de l'intégrité

 Outils de développement

(6)

7.1 Conception du schéma

relationnel au niveau conceptuel

 Schéma relationnel : niveau conceptuel

– tables

– colonnes

 types, domaines, ...

– contraintes d ’intégrité

 clés primaires, étrangères, ...

 Input à la conception

– modèle conceptuel des données

(persistantes)

(7)

7.1.1 Première ébauche du

schéma : une table par classe

Personne

<<table>>

Membre

<<table>> PrêtEnCours

<<table>>

PrêtArchivé

<<table>>

Employé

<<table>>

Catégorie

<<table>>

Auteur

<<table>>

Editeur

<<table>>

Livre

<<table>> Exemplaire

<<table>>

Prêt

<<table>>

Utilisateur

<<table>>

(8)

7.1.2 Traduction des attributs

 Attribut de la classe -> colonne de la table

Livre {Clé candidate: ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée

<<table>>

Livre {UNIQUE: ISBN}

ISBN : String titre : String

annéeParution : TypeDonnéesAnnée

(9)

7.1.2.1 TRADUCTION DES CONTRAINTES D'IDENTIFICATION (UNIQUE)

 Contrainte UNIQUE -> clé candidate relationnelle

– clé primaire ?

Livre {Clé candidate: ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée

<<table>>

Livre {UNIQUE: ISBN}

ISBN : String titre : String

annéeParution : TypeDonnéesAnnée

(10)

7.1.2.2 TRADUCTION DES TYPES DE DONNÉES

Type OCL Type SQL2 Oracle 8

Boolean BIT(1) Non supporté (utiliser CHAR(1) + CHECK)

Integer INTEGER ou SMALLINT NUMBER(n)

String CHARACTER (CHAR) (n), CHARACTER

VARYING (VARCHAR) (n) VARCHAR2(n), LONG ou LONG VARCHAR (chaîne jusqu'à 2G), CLOB (chaîne jusqu'à 4G), NCLOB (chaîne pour caractères encodés sur plusieurs octets)

Real NUMERIC(p,s) (précision exacte),

DECIMAL(p,s), REAL, DOUBLE PRECISION, FLOAT(p)

NUMBER(p,s)

Enum{v1,…vn} CHARACTER (CHAR) ou VARCHER + CHECK … IN (v1,…,vn) (possibilité de création de domaine)

Domaine non supporté

DATE DATE inclut TIME

TIME

TIMESTAMP

BIT(n), BIT VARYING(n) RAW(n : max = 255), LONG RAW (binaire jusqu'à 2G), BLOB (binaire jusqu'à 4G)

BFILE (pointeur à un fichier externe)

(11)

Types de données déclarés

 Domaine pas toujours supporté par le dialecte SQL

Livre {UNIQUE: ISBN}

ISBN : String titre : String

annéeParution : TypeDonnéesAnnée

TypeDonnéesAnnée {Integer > 0 }

<<datatype>>

Livre {Clé candidate: ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée

<<table>>

DomaineAnnée {INTEGER CHECK value > 0 }

<<domain>>

(12)

7.1.2.3 TYPES ÉNUMÉRÉS

 Petit domaine invariant

– création d ’un domaine VARCHAR + CHECK

Exemplaire

{Clé candidate : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : DomaineStatut

<<table>>

DomaineStatut

{VARCHAR(15) CHECK value IN ('prêté','disponible','retiré')}

<<domain>>

Exemplaire {UNIQUE: idExemplaire}

idExemplaire : String dateAchat : Date

statut : enum(prêté, disponible, retiré)

(13)

Création d ’une table

 Gros domaine ou extensible

– création d ’une table à part

– utilisé comme liste de valeurs (LOV Designer)

– introduction d ’une clé primaire artificielle ?

Exemplaire

{Clé candidate : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : VARCHAR(15)

<<table>>

DomaineStatut {Clé primaire : statut}

statut : VARCHAR(15)

<<table>>

(14)

7.1.2.4 TYPES COMPLEXES

 1. Représentation explicite des attributs du type complexe

Membre

adresse : typeDonnéesAdresse

typeDonnéesAdresse numéroCivique

numéroAppartement nomRue

nomVille nomProvince nomPays codePostal

<<datatype>>

Membre numéroCivique

numéroAppartement nomRue

nomVille nomProvince nomPays codePostal

<<table>>

(15)

2. Création d'une nouvelle table

 N.B. Pas de partage de la même adresse !

Membre

{Clé primaire : idMembre}

idMembre

<<table>>

Adresse

{Clé primaire : idMembre}

idMembre numéroCivique numéroAppartement nomRue

nomVille nomProvince nomPays codePostal

<<table>>

Membre

adresse : typeDonnéesAdresse

typeDonnéesAdresse numéroCivique

numéroAppartement nomRue

nomVille nomProvince nomPays codePostal

<<datatype>>

(16)

7.1.2.5 QUALIFICATEUR

 Colonne dans la table du rôle opposé

– voir 7.1.3.2

Groupe nbMaximumInscrits Cours

{UNIQUE:sigle}

sigle titre

nbCrédits 1 0..1

numéro session numéro

session

1 0..1

Groupe

{Clé primaire : sigle, numéro, session}

sigle numéro session

nbMaximumInscrits

<<table>>

Cours {Clé primaire :sigle}

sigle titre nbCrédits

<<table>>

(17)

7.1.2.6 DISCRIMINANT

 Redondant ? Utilisateur

{UNIQUE :idUtilisateur}

idUtilisateur : String motPasse : String catégorieUtilisateur

Membre

téléphoneRésidence : String

$ nbMaxPrêts : Integer = 5

$ duréeMaxPrêts : Integer = 7 Employé

{UNIQUE : codeMatricule}

codeMatricule : String

catégorieEmployé : enum(bibliothécaire, commis)

{disjointe, complète}

Utilisateur {Clé candidate : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

DomaineCatégorieUtilisateur

{VARCHAR(14) CHECK value IN ('employé, 'membre')}

<<domain>>

(18)

7.1.2.7 ATTRIBUT MULTIVALUÉ

 Table à part

– clé étrangère + colonne pour l ’attribut

 Petit tableau de taille fixe

n colonnes (valeurs nulles)

 Encodage

– invisible au SGBD

 Oracle8

– VARRAY, NESTED TABLE

(19)

7.1.2.8 COMPRESSION DES VALEURS DES ATTRIBUTS DE GRANDE TAILLE

 Supporté par le SGBD ?

 Multimédia

(20)

7.1.2.9 CRÉATION DE TABLES SUPPLÉMENTAIRES POUR LES ATTRIBUTS DE CLASSE

MembreGénéral nbMaxPrêts : INTEGER = 5 duréeMaxPrêts : INTEGER = 7

<<table>>

Membre

téléphoneRésidence : String

$ nbMaxPrêts : Integer = 5

$ duréeMaxPrêts : Integer = 7

Membre

téléphoneRésidence : VARCHAR(15)

<<table>>

(21)

27/02/22 © Robert Godin. Tous droits réservés 21

7.1.3 Réalisation de l'identité par les clés primaires

MembreGénéral {Clé primaire : noSequence}

<<table>>

Personne

{Clé primaire : noSequence}

noSequence : INTEGER nom : VARCHAR2(20) prénom : VARCHAR2(20)

<<table>>

Membre {Clé primaire : noSequence}

noSequence : INTEGER

téléphoneRésidence : VARCHAR(15)

<<table>>

PrêtEnCours

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>>

PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE

<<table>>

Employé {Clé primaire : noSequence}

noSequence : INTEGER {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

Catégorie

<<table>>

Auteur

{Clé primaire : noSequence}

noSequence

<<table>>

Editeur

<<table>>

Livre {Clé primaire : ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée

<<table>> Exemplaire

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : DomaineStatut

<<table>>

Prêt

{Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

<<table>>

Utilisateur {Clé primaire : noSequence}

noSequence

{Clé candidate : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

AuteurLivre

{Clé primaire : noSequence, ISBN}

noSequence ISBN

(22)

7.1.3.1 CRÉATION D'UNE CLÉ PRIMAIRE ARTIFICIELLE

 De manière systématique ?

 Mécanisme de SEQUENCE Oracle

PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE

<<table>>

PrêtEnCours

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>>

Prêt

{Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

<<table>>

Prêt

datePrêt : Date

PrêtArchivé dateRetour : Date

PrêtEnCours

(23)

7.1.3.2 UTILISATION D'UN IDENTIFIANT NATUREL COMME CLÉ PRIMAIRE

 1. Utilisation d'un identifiant naturel (UNIQUE)

 Si identifiant naturel trop lourd

– introduire clé primaire artificielle Livre

{Clé candidate: ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée

<<table>>

Livre {Clé primaire: ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée

<<table>>

(24)

2. Utilisation du qualificateur

Groupe nbMaximumInscrits Cours

{UNIQUE:sigle}

sigle titre

nbCrédits 1 0..1

numéro session numéro

session

1 0..1

Groupe

{Clé primaire : sigle, numéro, session}

sigle numéro session

nbMaximumInscrits

<<table>>

Cours

{Clé primaire :sigle}

sigle titre

nbCrédits

<<table>>

(25)

7.1.3.3 IDENTIFIANT NATUREL POUR UNE SPÉCIALISATION

 Éviter de changer de clé primaire dans le contexte d ’une hiérarchie de généralisation

 Si la table du parent est omise

– considérer identifiant naturel de la

spécialisation

(26)

27/02/22 © Robert Godin. Tous droits réservés .

26

7.1.4 Traduction des associations

Prêt

{Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

<<table>>

Personne

{Clé primaire : noSequence}

noSequence : INTEGER nom : VARCHAR2(20) prénom : VARCHAR2(20)

<<table>>

Membre {Clé primaire : noSequence}

noSequence : INTEGER

téléphoneRésidence : VARCHAR(15)

<<table>>

PrêtEnCours

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>> PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE

<<table>>

Employé {Clé primaire : noSequence}

noSequence : INTEGER {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

Catégorie {Clé primaire : code}

code : VARCHAR(10) descripteur : VARCHAR(20) codeParent : VARCHAR(10)

<<table>>

Auteur

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>>

Editeur

{Clé primaire : nomEditeur}

nomEditeur : VARCHAR(20)

<<table>>

Livre {Clé primaire : ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée nomEditeur : VARCHAR(20) code : VARCHAR(10)

<<table>> Exemplaire

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : DomaineStatut ISBN : CHAR(13)

<<table>>

Utilisateur {Clé primaire : noSequence}

noSequence

{Clé candidate : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

MembreGénéral {Clé primaire : noSequence}

<<table>>

AuteurLivre

{Clé primaire : noSequence, ISBN}

noSequence : INTEGER

{Clé candidate : ISBN, ordreAuteur}

ISBN : CHAR(13) ordreAuteur : INTEGER

<<table>>

{Un Auteur ne peut exister sans AuteurLivre}

{Un Livre ne peut exister sans AuteurLivre}

noSequenceUtilisateur

{Un Livre ne peut exister sans Exemplaire}

(27)

7.1.4.1 CAS GÉNÉRAL : TRADUCTION D'UNE ASSOCIATION PAR UNE TABLE

Auteur

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>> Livre

{Clé primaire : ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée

<<table>>

AuteurLivre

{Clé primaire : noSequence, ISBN}

noSequence : INTEGER ISBN : CHAR(13)

<<table>>

{Un Auteur ne peut exister

sans AuteurLivre} {Un Livre ne peut exister

sans AuteurLivre}

Auteur

1..* 1..*

1..* 1..*

Livre {UNIQUE: ISBN}

ISBN : String titre : String

annéeParution : TypeDonnéesAnnée

(28)

7.1.4.2 TRADUCTION D'UN RÔLE

ORDONNÉ POUR UNE ASSOCIATION

Auteur

1..* 1..*

1..* 1..*

Livre {UNIQUE: ISBN}

ISBN : String titre : String

annéeParution : TypeDonnéesAnnée {ordonné}

A u teu r

{C lé p rim a ire : n o S e q u e n c e } n o S eq u e n c e : IN T E G E R

< < ta ble > >

A u te u rL iv re

{C lé p rim a ire : n o S e q u en c e , IS B N } n o S e q u e n c e : IN T E G E R

{C lé c a n d id a te : IS B N , o rd re A u te u r} IS B N : C H A R (1 3 )

o rd re A u te u r : IN T E G E R

< < ta b le > >

L ivre {C lé p rim a ire : IS B N } IS B N : C H A R (1 3 ) titre : V A R C H A R (5 0 )

a n n é e P a ru tio n : D o m a in e A n n é e

< < ta b le > >

(29)

7.1.4.3 CLASSE ASSOCIATIVE

Cours {UNIQUE : sigle}

sigle titre nbCrédits Etudiant

{UNIQUE : codePermanent}

codePermanent nom

prénom

* * * *

NoteObtenue note

session

Cours

{Clé primaire : sigle}

sigle titre nbCrédits

<<table>>

Etudiant

{Clé primaire : codePermanent}

codePermanent nom

prénom

<<table>>

NoteObtenue

{Clé primaire : codePermament, sigle}

codePermament sigle

note session

<<table>>

(30)

7.1.4.4 CAS UN À PLUSIEURS

 1. Traduction par une table ?

Catégorie {UNIQUE: code}

code : String

descripteur : String

1 1 **

Livre {UNIQUE: ISBN}

ISBN : String titre : String

annéeParution : TypeDonnéesAnnée

Livre {C lé prim aire : IS B N } IS B N : C H A R(13) titre : V A R C H A R (50 )

annéeP arution : D om aineA nné e

< < table> >

C atégorie {C lé prim aire : code}

code : V A R C H A R(10) descripteu r : V A R C H A R (20)

< < table> >

C atég orieLivre {C lé prim aire : IS B N } IS B N : C H A R(13) code : V A R C H A R(10 )

< < table> >

(31)

2. Traduction par l'ajout d'une clé étrangère à privilégier

 Navigation plus performante

Catégorie {UNIQUE: code}

code : String

descripteur : String 1 1 **

Livre {UNIQUE: ISBN}

ISBN : String titre : String

annéeParution : TypeDonnéesAnnée

Livre {Clé primaire : ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée code : VARCHAR(10)

<<table>>

Catégorie {Clé primaire : code}

code : VARCHAR(10)

descripteur : VARCHAR(20)

<<table>>

(32)

Renommer la clé

étrangère au besoin

Utilisateur {Clé primaire : noSequence}

noSequence

{Clé candidate : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

noSequenceUtilisateur

Prêt {Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

<<table>>

(33)

7.1.4.5 CAS UN À UN

 1. Une clé étrangère (du côté obligatoire)

Passeport

{UNIQUE : noPasseport}

noPasseport dateExpiration Citoyen

{UNIQUE : noAssurranceSociale}

noAssurranceSociale nom

prénom

0..1

1 0..1

1

Passeport {Clé primaire : noPasseport}

noPasseport dateExpiration

{Clé candidate : noAssurranceSociale}

noAssurranceSociale

<<table>>

Citoyen

{Clé primaire : noAssurranceSociale}

noAssurranceSociale nom

prénom

<<table>>

(34)

2. Une nouvelle table

Homme

{UNIQUE : noAssurranceSociale}

noAssurranceSociale nom

prénom

Femme

{UNIQUE : noAssurranceSociale}

noAssurranceSociale nom

prénom 0..1

0..1

0..1 0..1

grasAVie vieAGras

Mariage

Homme

{Clé primaire : noAssurranceSociale}

noAssurranceSociale nom

prénom

<<table>>

Femme

{Clé primaire : noAssurranceSociale}

noAssurranceSociale nom

prénom

<<table>>

Mariage

{Clé candidate : noAssSocFemme}

noAssSocFemme

{Clé candidate : noAssSocHomme}

noAssSocHomme

<<table>>

(35)

3. Fusion

 Cas 1-1 obligatoire

(36)

7.1.4.6 CAS DE L'AGRÉGATION

 Comme une association normale

Catégorie {UNIQUE: code}

code : String

descripteur : String

enfant

0..1

* parent 0..1

*

Catégorie {Clé primaire : code}

code : VARCHAR(10)

descripteur : VARCHAR(20) codeParent : VARCHAR(10)

<<table>>

codeParent

(37)

Composition

 Cas 1-1

– ~ attribut complexe

 Mode SQL CASCADE

 Oracle8

– VARRAY, NESTED TABLE

(38)

7.1.5 Traduction des relations de généralisation/spécialisation

 Délégation

 Fusion

 Concaténation

(39)

7.1.5.1 DÉLÉGATION

Personne

{Clé primaire : noSequence}

noSequence : INTEGER nom : VARCHAR2(20) prénom : VARCHAR2(20)

<<table>>

Membre {Clé primaire : noSequence}

noSequence : INTEGER

téléphoneRésidence : VARCHAR(15)

<<table>>

Employé {Clé primaire : noSequence}

noSequence : INTEGER {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

Auteur

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>>

Utilisateur {Clé primaire : noSequence}

noSequence : INTEGER {Clé candidate : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

/ catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

{catégorieUtilisateur doit être cohérent avec la table d'appartenance de l'objet}

(40)

Changement de clé primaire ?

 Extraire le téléphone résidence d'un Membre possédant l'idUtilisateur

12345

Personne

{Clé primaire : noSequence}

noSequence : INTEGER nom : VARCHAR2(20) prénom : VARCHAR2(20)

<<table>> Utilisateur

{Clé candidate : noSequence}

noSequence

{Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

Employé {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

Membre {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10)

téléphoneRésidence : VARCHAR(15)

<<table>>

(41)

Traduction de la contrainte {disjointe, complète}

Prêt

{Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

<<table>>

{Exclusives et une des deux est nécessaire}

PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE

<<table>>

PrêtEnCours

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>>

Prêt datePrêt : Date {disjointe, complète}

PrêtArchivé dateRetour : Date

PrêtEnCours

(42)

7.1.5.1.1 Cas de la multi-classification et de l'héritage multiple

Auteur

{Clé prim aire : noS equence}

noS equence

<<table>>

Utilisateur {Clé prim aire : noS equenc e}

noS equenc e

{Clé c andidate : idUtilisateur}

idUtilis ateur : VARC HAR(10) m otP asse : VAR CHAR(10)

catégorieUtilisateur : D om aineC atégorieUtilis ateur

<<table>>

Em ployé {Clé prim aire : noS equenc e}

noS equenc e : INTEG ER {Clé c andidate : c odeM atricule}

codeM atric ule : CH AR(6)

catégorieE m ployé : D om aineC atégorieEm ployé

<<table>>

M em bre {Clé prim aire : noS equenc e}

noS equenc e : INT EG ER

téléphoneR ésidenc e : VARCH AR(15)

<<table>>

AuteurM em bre {Clé prim aire : noS equenc e}

noS equenc e

1. Créer une table de jointure

(43)

Alternatives

 2. Identité commune sans table de jointure

 3. Identité séparée et redondance

de données

(44)

7.1.5.2 ANALOGIE AVEC UNE ASSOCIATION UN À UN

 Clé étrangère

– dans l ’enfant

– dans le parent ???

 Approche Arc de Designer

 Fusion

– vers le parent (approche par fusion)

– vers l ’enfant (approche par concaténation)

 Nouvelle table ???

(45)

7.1.5.3 FUSION

Prêt {Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

{catégoriePrêt = 'prêtEnCours' ssi dateRetour nulle}

dateRetour[0..1] : DATE

catégoriePrêt : DomaineCatégoriePrêt

<<table>>

DomaineCatégoriePrêt

{VARCHAR(15) CHECK valeur IN ('prêtEnCours', 'prêtArchivé')}

<<domain>>

Prêt

{Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

<<table>>

{Exclusives et une des deux est nécessaire}

PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE

<<table>>

PrêtEnCours

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>>

(46)

7.1.5.4 CONCATÉNATION

{La contrainte de clé primaire est globale pour les deux tables}

PrêtEnCours {Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

<<table>>

PrêtArchivé {Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

<<table>>

Exemplaire

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : DomaineStatut ISBN : CHAR(13)

<<table>>

Utilisateur {Clé candidate : noSequence}

noSequence

{Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

noSequenceUtilisateur noSequenceUtilisateur Prêt

{Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceUtilisateur : INTEGER idExemplaire : VARCHAR(10)

<<table>>

{Exclusives et une des deux est nécessaire}

PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE

<<table>>

PrêtEnCours

{Clé primaire : noSequence}

noSequence : INTEGER

<<table>>

Conserver une table

pour le parent ?

(47)

Cas d ’une référence au parent

Membre {Clé primaire : noSequence}

noSequence : INTEGER nom : VARCHAR2(20) prénom : VARCHAR2(20) {Clé candidate : idUtilisateur}

idUtilisatuer : VARCHAR(10) motPasse : VARCHAR(10)

téléphoneRésidence : VARCHAR(15)

<<table>>

Employé {Clé primaire : noSequence}

noSequence : INTEGER nom : VARCHAR2(20) prénom : VARCHAR2(20) {Clé candidate : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10)

catégorieEmployé : DomaineCatégorieEmployé {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

<<table>>

{exclusives}

noSequenceEmployé

noSequenceMembre

Prêt

{Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

noSequenceEmployé : INTEGER noSequenceMembre : INTEGER idExemplaire : VARCHAR(10)

<<table>>

(48)

7.1.5.5 TRADUCTION DES GÉNÉRALISATIONS POUR SYLERAT

Membre {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10)

téléphoneRésidence : VARCHAR(15)

<<table>>

PrêtEnCours {Clé primaire : noSequence}

noSequence : INTEGER datePrêt : DATE

idUtilisateur : VARCHAR(10) idExemplaire : VARCHAR(10)

<<table>>

PrêtArchivé {Clé primaire : noSequence}

noSequence : INTEGER dateRetour : DATE datePrêt : DATE

idUtilisateur : VARCHAR(10) idExemplaire : VARCHAR(10)

<<table>>

Employé {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

Catégorie {Clé primaire : code}

code : VARCHAR(10) descripteur : VARCHAR(20) codeParent : VARCHAR(10)

<<table>>

Auteur

{Clé primaire : noSequence}

noSequence : INTEGER nom : VARCHAR2(20) prénom : VARCHAR2(20)

<<table>>

Editeur

{Clé primaire : nomEditeur}

<<table>>

Livre {Clé primaire : ISBN}

ISBN : CHAR(13) titre : VARCHAR(50)

annéeParution : DomaineAnnée nomEditeur : VARCHAR(20) code : VARCHAR(10)

<<table>> Exemplaire

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : DomaineStatut ISBN : CHAR(13)

<<table>>

Utilisateur {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10) nom : VARCHAR2(20) prénom : VARCHAR2(20)

/ catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

MembreGénéral {Clé primaire : noSequence}

<<table>>

AuteurLivre

{Clé primaire : noSequence, ISBN}

noSequence : INTEGER

{Clé candidate : ISBN, ordreAuteur}

ISBN : CHAR(13) ordreAuteur : INTEGER

<<table>>

{Un Auteur ne peut exister sans AuteurLivre}

{Un Livre ne peut exister sans AuteurLivre}

{Un Livre ne peut exister sans Exemplaire}

{Exclusives et une des deux est nécessaire}

{CatégorieUtilisateur doit être cohérente avec la table d'appartenance}

{Lors d'un retour le PrêtArchivé est généré à partir du PrêtEn Cours en réutilisant le même noSequence}

(49)

7.1.6 Traduction des autres contraintes

PrêtEnCours

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) datePrêt : DATE

idUtilisateur : VARCHAR(10)

<<table>>

PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER {dateRetour >= datePrêt}

dateRetour : DATE datePrêt : DATE

idUtilisateur : VARCHAR(10) idExemplaire : VARCHAR(10)

<<table>>

Exemplaire

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : DomaineStatut

<<table>>

MembreGénéral {Clé primaire : noSequence}

noSequence

nbMaxPrêts : INTEGER = 5 duréeMaxPrêts : INTEGER = 7

<<table>>

{statut = 'prêté' si et seulement si un Prêt EnCours fait référence à l'Exemplaire}

{Le nombre de PrêtEnCours d'un Membre <= nbMaxPrêts}

Utilisateur {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10) nom : VARCHAR2(20) prénom : VARCHAR2(20)

/ catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

Membre {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10)

téléphoneRésidence : VARCHAR(15)

<<table>>

(50)

7.1.7 Niveau de mise en œuvre des

contraintes d'intégrité : client ou serveur de BD ?

Robustesse

Interactivité

Performance

(51)

7.1.8 Représentation des

contraintes d'intégrité en SQL

Voir chap.7, volume I

Deux catégories

Contrainte d'intégrité statique

 respectée pour chacun des états de la BD

Contrainte d'intégrité dynamique

 contrainte sur changements d'états

(52)

7.1.8.1 CONTRAINTES STATIQUES

 Mécanismes déclaratifs (à privilégier)

– PRIMARY KEY, UNIQUE, NOT NULL, DOMAIN, FOREIGN KEY, CHECK, ASSERTION

 Procédural

– TRIGGER (SQL3)

 plus complexe à coder

plus sujet à erreur

 parfois plus performant

 parfois inévitables (limite des mécanismes déclaratifs)

(53)

Contrainte sur le domaine d'une colonne

CREATE DOMAIN DomaineCatégorieUtilisateur AS

VARCHAR(14) CHECK(VALUE IN ('employé', 'membre')) CREATE TABLE Utilisateur

(idUtilisateur VARCHAR(10) NOT NULL,

motPasse VARCHAR(10) NOT NULL,

nom VARCHAR(20) NOT NULL,

prénom VARCHAR(20) NOT NULL,

catégorieUtilisateur DomaineCatégorieUtilisateur NOT NULL, PRIMARY KEY (idUtilisateur)

)

DomaineCatégorieUtilisateur

{VARCHAR(14) CHECK value IN ('employé, 'membre')}

<<domain>>

Utilisateur {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10) nom : VARCHAR2(20) prénom : VARCHAR2(20)

/ catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

(54)

Contrainte de clé primaire

CREATE TABLE Utilisateur

(idUtilisateur VARCHAR(10) NOT NULL,

PRIMARY KEY (idUtilisateur) )

Utilisateur {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10) nom : VARCHAR2(20) prénom : VARCHAR2(20)

/ catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

(55)

Contrainte de clé candidate

CREATE TABLE Employé

(idUtilisateur VARCHAR(10) NOT NULL, codeMatricule CHAR(6) NOT NULL,

catégorieEmployé DomaineCatégorieEmployé NOT NULL, PRIMARY KEY (idUtilisateur),

UNIQUE (codeMatricule),

FOREIGN KEY (idUtilisateur) REFERENCES Utilisateur )

Employé {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

(56)

Contrainte d'intégrité référentielle

Employé {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

Utilisateur {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10) nom : VARCHAR2(20) prénom : VARCHAR2(20)

/ catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

CREATE TABLE Employé

(idUtilisateur VARCHAR(10) NOT NULL, codeMatricule CHAR(6) NOT NULL,

catégorieEmployé DomaineCatégorieEmployé NOT NULL, PRIMARY KEY (idUtilisateur),

UNIQUE (codeMatricule),

FOREIGN KEY (idUtilisateur) REFERENCES Utilisateur )

Politique NO ACTION par défaut

(57)

Contrainte intra-ligne

CREATE TABLE PrêtArchivé

(noSequence INTEGER NOT NULL,

datePrêt DATE NOT NULL,

dateRetour DATE NOT NULL,

idUtilisateur VARCHAR(10) NOT NULL, idExemplaire VARCHAR(10) NOT NULL, PRIMARY KEY (noSequence),

FOREIGN KEY (idUtilisateur) REFERENCES Utilisateur, FOREIGN KEY (idExemplaire) REFERENCES Exemplaire, CHECK (dateRetour >= datePrêt)

)

PrêtArchivé

{Clé primaire : noSequence}

noSequence : INTEGER {dateRetour >= datePrêt}

dateRetour : DATE datePrêt : DATE

idUtilisateur : VARCHAR(10) idExemplaire : VARCHAR(10)

<<table>>

(58)

Autres cas

 CHECK complexes

– non supporté par Oracle

 ASSERTION

– non supporté par Oracle

 TRIGGER

(59)

{Un Editeur ne peut exister sans qu'un Livre y fasse référence}

CREATE TABLE Editeur

(nomEditeur VARCHAR(20) NOT NULL,

ville VARCHAR(20) NOT NULL,

PRIMARY KEY (nomEditeur),

CHECK nomEditeur IN (SELECT nomEditeur FROM Livre) DEFERRABLE INITIALLY DEFERRED

)

CREATE TRIGGER BDULivreInterdiction BEFORE DELETE OR UPDATE ON Livre FOR EACH ROW

BEGIN

souleverUneException;

END

Ne peut être réalisée par TRIGGER seulement !

(60)

Exemple avec ASSERTION

Membre {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10)

téléphoneRésidence : VARCHAR(15)

<<table>>

{Le nombre de PrêtEnCours d'un Membre <= nbMaxPrêts}

MembreGénéral {Clé primaire : noSequence}

noSequence

nbMaxPrêts : INTEGER = 5 duréeMaxPrêts : INTEGER = 7

<<table>>

CREATE ASSERTION ContrainteNbMaxPrêts CHECK

((NOT EXISTS (SELECT *

FROM Membre, MembreGénéral

WHERE MembreGénéral.nbMaxPrêts >

(SELECT COUNT(*) FROM PrêtEnCours

WHERE Membre.idUtilisateur = PrêtEnCours.idUtilisateur))))

(61)

Réalisation avec TRIGGER

CREATE TRIGGER BIPrêtEnCoursVérifierNbMaxPrêts BEFORE INSERT ON PrêtEnCours

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

WHEN

((EXISTS

(SELECT * FROM MEMBRES

WHERE idUtilisateur = lignesAprès.idUtilisateur)) AND

((SELECT COUNT(*) FROM PrêtEnCours

WHERE ligneAprès.idUtilisateur=PrêtEnCours.idUtilisateur) >=

(SELECT nbMaxPrêts FROM MembreGénéral))) BEGIN

souleverUneException;

END

CREATE TRIGGER BUPrêtEnCours BEFORE UPDATE ON PrêtEnCours FOR EACH ROW

BEGIN

souleverUneException;

END

(62)

PrêtEnCours

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) datePrêt : DATE

idUtilisateur : VARCHAR(10)

<<table>>

{statut = 'prêté' si et seulement si un Prêt EnCours fait référence à l'Exemplaire}

Exemplaire

{Clé primaire : idExemplaire}

idExemplaire : VARCHAR(10) dateAchat : Date

statut : DomaineStatut ISBN : CHAR(13)

<<table>>

CREATE ASSERTION ContrainteStatutPrêté CHECK

((NOT EXISTS

((SELECT idExemplaire FROM Exemplaire

WHERE statut = 'prêté') EXCEPT (SELECT idExemplaire

FROM PrêtEnCours))) AND (NOT EXISTS

((SELECT idExemplaire

FROM PrêtEnCours) EXCEPT (SELECT idExemplaire

FROM Exemplaire

WHERE statut = 'prêté'))))

DEFERRABLE INITIALLY DEFERRED

(63)

Par TRIGGER : forcer le changement de statut

CREATE TRIGGER AIPrêtEnCoursModifierStatutExemplaire AFTER INSERT ON PrêtEnCours

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

BEGIN

UPDATE Exemplaire

SET statut = 'prêté'

WHERE idExemplaire = ligneAprès.idExemplaire;

END

CREATE TRIGGER ADPrêtEnCoursModifierStatutExemplaire AFTER DELETE ON PrêtEnCours

REFERENCING

OLD ROW AS ligneAvant FOR EACH ROW

BEGIN

UPDATE Exemplaire

SET statut = 'disponible'

WHERE idExemplaire = ligneAvant.idExemplaire;

END

(64)

Membre {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10)

téléphoneRésidence : VARCHAR(15)

<<table>>

Employé {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) {Clé candidate : codeMatricule}

codeMatricule : CHAR(6)

catégorieEmployé : DomaineCatégorieEmployé

<<table>>

Utilisateur {Clé primaire : idUtilisateur}

idUtilisateur : VARCHAR(10) motPasse : VARCHAR(10) nom : VARCHAR2(20) prénom : VARCHAR2(20)

/ catégorieUtilisateur : DomaineCatégorieUtilisateur

<<table>>

{Exclusives et une des deux est nécessaire}

{CatégorieUtilisateur doit être cohérente avec la table d'appartenance}

CREATE ASSERTION ContrainteGénéralisationUtilisateur CHECK

((NOT EXISTS (SELECT * FROM Utilisateur, Employé

WHERE catégorieUtilisateur = ‘membre’

AND Utilisateur.idUtilisateur = Employé.idUtilisateur)) AND

(NOT EXISTS (SELECT *

FROM Utilisateur, Membre

WHERE catégorieUtilisateur = ‘employé’

AND Utilisateur.idUtilisateur = Employé.idUtilisateur)) AND

(NOT EXISTS

((SELECT idUtilisateur FROM Utilisateur) EXCEPT

((SELECT idUtilisateur FROM Employé)

UNION (SELECT idUtilisateur FROM MEMBRE)))))

(65)

{CatégorieUtilisateur doit être cohérente avec la table d'appartenance} par TRIGGER

CREATE TRIGGER AIEmployéModifierCatégorie AFTER INSERT ON Employé

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

BEGIN

UPDATE Utilisateur

SET catégorieUtilisateur = 'employé'

WHERE idUtilisateur = ligneAprès.idUtilisateur;

END

CREATE TRIGGER AIMembreModifierCatégorie AFTER INSERT ON Membre

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

BEGIN

UPDATE Utilisateur

SET catégorieUtilisateur = 'membre'

WHERE idUtilisateur = ligneAprès.idUtilisateur;

END

(66)

{Exclusives et une des deux est nécessaire} par CHECK

CREATE TABLE Utilisateur

(idUtilisateur VARCHAR(10) NOT NULL, motPasse VARCHAR(10) NOT NULL,

nom VARCHAR(10) NOT NULL,

prénom VARCHAR(10) NOT NULL,

catégorieUtilisateur DomaineCatégorieUtilisateur NOT NULL, PRIMARY KEY (idUtilisateur),

CHECK

((idUtilisateur IN (SELECT idUtilisateur FROM Employé) OR idUtilisateur IN (SELECT idUtilisateur FROM Membre)) AND

NOT (idUtilisateur IN (SELECT idUtilisateur FROM Employé) AND idUtilisateur IN (SELECT idUtilisateur FROM Membre)))

DEFERRABLE INITIALLY DEFERRED )

Impossible avec TRIGGER non DEFERRABLE

(67)

7.1.8.2 CONTRAINTES DYNAMIQUES

 Interdit de faire un prêt à un Membre qui possède un retard

CREATE TRIGGER BIPrêtEnCoursVérifierRetard BEFORE INSERT ON PrêtEnCours

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

WHEN

((EXISTS

(SELECT * FROM MEMBRES

WHERE idUtilisateur = lignesAprès.idUtilisateur))AND (EXISTS

(SELECT * FROM PrêtEnCours, MembreGénéral

WHERE ligneAprès.idUtilisateur = idUtilisateur AND (CURRENT_DATE - datePrêt) > duréeMaxPrêts)))

BEGIN

souleverUneException;

END

(68)

{le statut de l'Exemplaire doit être disponible avant qu'un prêt ne soit effectué}

CREATE TRIGGER BIPrêtEnCoursVérifierDisponibilité BEFORE INSERT ON PrêtEnCours

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

WHEN (EXISTS

(SELECT * FROM Exemplaire

WHERE ligneAprès.idExemplaire = idExemplaire AND statut <> 'disponible'))

BEGIN

souleverUneException;

END

(69)

Archivage des prêts lors d'un retour

CREATE TRIGGER ADPrêtEnCoursArchiverPrêt AFTER DELETE ON PrêtEnCours

REFERENCING

OLD ROW AS ligneAvant FOR EACH ROW

BEGIN

INSERT INTO PrêtArchivé VALUES

SELECT MAX(noSequence)+1, ligneAvant.datePrêt, CURRENT_DATE, ligneAvant.idUtilisateur,

ligneAvant.idExemplaire FROM PrêtArchivé;

END

(70)

7.1.9 Exemple de schéma SQL pour SyLeRat

Eviter la circularité des définitions

CREATE TABLE Utilisateur (…,

CHECK

((idUtilisateur IN (SELECT idUtilisateur FROM Employé) OR idUtilisateur IN (SELECT idUtilisateur FROM Membre)) AND

NOT (idUtilisateur IN (SELECT idUtilisateur FROM Employé) AND idUtilisateur IN (SELECT idUtilisateur FROM Membre)))

DEFERRABLE INITIALLY DEFERRED )

CREATE TABLE Employé (…,

FOREIGN KEY (idUtilisateur) REFERENCES Utilisateur )

CREATE TABLE Membre (…,

FOREIGN KEY (idUtilisateur) REFERENCES Utilisateur

)

(71)

Utilisation du ALTER TABLE

CREATE TABLE Utilisateur (…

)

CREATE TABLE Employé (…,

FOREIGN KEY (idUtilisateur) REFERENCES Utilisateur )

CREATE TABLE Membre (…,

FOREIGN KEY (idUtilisateur) REFERENCES Utilisateur )

ALTER TABLE Utilisateur

ADD CONSTRAINT contrainteGénéralisationComplèteDisjointe CHECK

((idUtilisateur IN (SELECT idUtilisateur FROM Employé) OR idUtilisateur IN (SELECT idUtilisateur FROM Membre)) AND

NOT (idUtilisateur IN (SELECT idUtilisateur FROM Employé) AND idUtilisateur IN (SELECT idUtilisateur FROM Membre)))

DEFERRABLE INITIALLY DEFERRED

(72)

Combinaison de TRIGGER

CREATE TRIGGER BIPrêtEnCoursVérifierNbMaxPrêts BEFORE INSERT ON PrêtEnCours

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

WHEN ((EXISTS

(SELECT * FROM MEMBRES

WHERE idUtilisateur = lignesAprès.idUtilisateur)) AND

… END

CREATE TRIGGER BIPrêtEnCoursVérifierRetard BEFORE INSERT ON PrêtEnCours

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

WHEN ((EXISTS

(SELECT * FROM MEMBRES

WHERE idUtilisateur = lignesAprès.idUtilisateur))AND

… END

CREATE TRIGGER BIPrêtEnCoursVérifierDisponibilité BEFORE INSERT ON PrêtEnCours

Contrôler l'ordre d'exécution

Améliorer la performance

(73)

CREATE TRIGGER BIPrêtEnCoursVérifierNbMaxRetardDisponibilité BEFORE INSERT ON PrêtEnCours

REFERENCING

NEW ROW AS ligneAprès FOR EACH ROW

WHEN

(((EXISTS

(SELECT * FROM MEMBRES

WHERE idUtilisateur = lignesAprès.idUtilisateur)) AND

((EXISTS

(SELECT * FROM PrêtEnCours, MembreGénéral

WHERE ligneAprès.idUtilisateur = idUtilisateur AND (CURRENT_DATE - datePrêt) > duréeMaxPrêts))

OR

((SELECT COUNT(*) FROM PrêtEnCours

WHERE ligneAprès.idUtilisateur=PrêtEnCours.idUtilisateur) >=

(SELECT nbMaxPrêts FROM MembreGénéral)) )

) OR

(EXISTS

(SELECT * FROM Exemplaire

WHERE ligneAprès.idExemplaire = idExemplaire AND statut <> 'disponible'))

) BEGIN

souleverUneException;

END

Une seule fois !

N.B. Contrôle plus fin avec PL/SQL

(74)

7.2 Conception du schéma

relationnel au niveau externe

 Ce que l ’utilisateur voit

 Sécurité

– utilisateurs, rôles, privilèges

– partir des cas d ’utilisation

 Tables virtuelles

(75)

7.2.1 Tables virtuelles

 Mécanisme d ’encapsulation

– isoler l ’utilisateur des détails du schéma

– indépendance logique des données

 Mécanisme de sécurité

– privilège d ’accès à la table

virtuelle seulement

(76)

Exemple d ’encapsulation

CREATE VIEW VueMembre AS

SELECT Utilisateur.idUtilisateur, motPasse, nom, prénom, téléphoneRésidence

FROM Utilisateur, Membre

WHERE Membre.idUtilisateur = Utilisateur.idUtilisateur CREATE VIEW VueEmployé AS

SELECT Utilisateur.idUtilisateur, motPasse, nom, prénom, codeMatricule, catégorieEmployé

FROM Utilisateur, Employé

WHERE Employé.idUtilisateur = Utilisateur.idUtilisateur

CREATE VIEW Prêt AS

(SELECT NULL, datePrêt, NULL, idUtilisateur, idExemplaire FROM PrêtEnCours)

UNION

(SELECT * FROM PrêtArchivé)

(77)

Exemple de mécanisme de sécurité

CREATE VIEW MesPrêts AS SELECT *

FROM Prêts

WHERE idUtilisateur = CURRENT_USER

(78)

7.2.2 Réalisation des

contraintes de sécurité

 Acteur (cas d ’utilisation) : ROLE SQL

– ROLE RôleAdministrateurSystème

 accès à tout

– ROLE RôleCommisAuPrêt

 tout en lecture (SELECT)

Membre, Utilisateur, PrêtEnCours, PrêtArchivé,

Exemplaire en écriture (INSERT, DELETE, UPDATE)

– ROLE RôleMembre

...

 GRANT ROLE xxx to authorizationID

(79)

Utilisation de TRIGGER

 Le prêt est interdit 1h00 et 7h00

CREATE TRIGGER BIPrêtEnCoursVérifierHeure BEFORE INSERT ON PrêtEnCours

FOR EACH ROW

WHEN (CURRENT_TIME > TIME '01:00:00') AND (CURRENT_TIME < TIME '07:00:00')

BEGIN

souleverUneException;

END

(80)

7.3 Niveau interne du schéma

relationnel : conception physique

 Input

– schéma (niveau conceptuel) initial

– estimations des volumes de données

– architecture

contraintes SGBD

contraintes plate-forme

– charge de travail

exigences de performance

 Output

– le « meilleur » schéma interne

solution approchée

(81)

7.3.1 Conception physique dans un contexte centralisé

 Organisations primaires

 Organisations

secondaires

(82)

Organisation primaire

Fichiers et paramètres d'allocation d'espace

– quel disque/site

 architectures RAID

– taille de bloc

– taille de fichier

 fixe

 allocation dynamique

– taille des granules

(83)

Organisation primaire (suite)

Paramètres d'allocation d'espace aux tables

– quels fichiers ?

– taille des granules

– homogène / hétérogène

– colonne externe ? (multimédia)

 chemin vers fichier externe

 URL

(84)

Organisation primaire (suite)

Paramètres du mécanisme d'allocation d'espace aux lignes

– position dans le fichier

 allocation sérielle, grappe, index primaire, hachage

 réservation d ’espace

 paramètres spécifiques à l ’organisation

– enregistrements

 taille fixe/variable

 chevauchant ou non

 compression

 cryptage

– gestion des identifiants d ’enregistrement (IDE)

(85)

Organisations secondaires

 Chemins d ’accès supplémentaires

– référence par IDE

 Index secondaire

 Organisation multidimensionnelle

 Listes

– SGBD réseau

 Collections de références

– SGBD objet

(86)

7.3.2 Le processus de conception

 Intrants

– schéma relationnel au niveau conceptuel

– volume des tables

 estimation difficile

– charge de travail

 partir des cas d ’utilisation

 Sortie

– schéma interne « optimal »

(87)

Problème d ’optimisation complexe

 Enjeux conflictuels

– lecture/écriture, espace/temps

 Grande quantité de paramètres

 Mesures approximatives

 Evolution des paramètres

 Solution approchée

– heuristiques

 Surveillance et mise au point

(88)

7.3.3 Heuristiques de conception

 Sous-ensemble des opérations

– en ordre d ’ importance

 Négliger le coût des mises à jour

 Négliger le coût en espace mémoire

 Méthode gloutonne

(89)

Méthode gloutonne

 Initialiser schémaInterne

– e.g. organisation sérielle pour chacune des tables

 Pour chacune des opération i (en ordre de priorité)

– trouver meilleur plan P pour opération

i

selon schémaInterne

– chercher amélioration de schémaInterne

 qui permet de produire un meilleur plan P ’

 sans pénaliser opération

1

… opération

i-1

– si P ’ meilleur que P

schémaInterne := schémaInterne amélioré

 Comment améliorer ?

– heuristiques d ’amélioration

(90)

7.3.4 Sélection par égalité

 SELECT ...

 FROM T

 WHERE X = uneValeurDeX

 Heuristique

– Si

 bonne sélectivité de X

 volume de données suffisant

– 1. Hachage sur X

– 2. Index primaire ou index groupant sur X

– 3. Index secondaire sur X

– N.B. Conditions particulières

(91)

Exemple glouton

 >>> sélectivité de ISBN

 >>> volume de données

TempsES (S=H) = 11ms

– volume assez stable

TempsES (S=IP) = 44ms

– sélection par intervalle non pertinente

TempsES (S=IS) = 55ms

Opération de priorité 1:

SELECT *

FROM Livre

WHERE ISBN = unISBN

Hachage<{Livre},{ISBN}>

Livre

<<table>>

(92)

Exemple

 Meilleur plan P avec schéma interne précédent

TempsES (BAL) > 50 010ms (meilleur cas)

 sélectivité de code = 1/4000

 volume de données suffisant

TempsES (S=H) = 143ms

conflit avec hachage sur ISBN

TempsES (S=IP) = 242ms

conflit ...

TempsES (S=IS) = 2827ms

seule possibilité pour éviter de pénaliser 1

Opération de priorité 2:

SELECT *

FROM Livre

WHERE code = unCode

Hachage<{Livre},{ISBN}>

Livre

<<table>>

IndexSecondaire<Livre,{code}>

(93)

Glouton : temps moyen sous-optimal

 Hypothèse

– sélection par ISBN : 50 fois par jour

– sélection par code : 30 fois par jour

– moyenne : (50*11 + 30*2827)/80 = 1067ms

 Pénaliser un peu opération 1…

– moyenne : (50*55 + 30*143)/80 = 88ms

Hachage<{Livre},{code}>

Livre

<<table>>

IndexSecondaire<Livre,{ISBN}>

(94)

 Meilleur plan P avec schéma interne précédent

TempsES (S=IS sur code) = 2827ms

TempsES ( S=IS sur la clé composée {code, annéeParution} ) = 99ms

 N.B. Index sur {code, annéeParution} utilisé pour :

Opération de priorité 3:

SELECT *

FROM Livre

WHERE code = unCode AND annéeParution = uneAnnée

Hachage<{Livre},{ISBN}>

Livre

<<table>>

IndexSecondaire<Livre,{code, annéeParution}>

Opération de priorité 2:

SELECT *

FROM Livre

code = unCode

(95)

Indexer les colonnes individuelles ?

TempsES(S) = 3 509ms

Hachage<{Livre},{ISBN}>

Livre

<<table>>

IndexSecondaire<Livre,{code}>

IndexSecondaire<Livre,{annéeParution}>

Opération de priorité 3:

SELECT *

FROM Livre

WHERE code = unCode AND annéeParution = uneAnnée

(96)

 Meilleur plan P avec schéma interne précédent

TempsES (BAL) > 50 010ms (meilleur cas)

TempsES ( S=IS sur annéeParution ) = 223 377 ms

Opération de priorité 4:

SELECT *

FROM Livre

WHERE annéeParution = uneAnnée

Hachage<{Livre},{ISBN}>

Livre

<<table>>

IndexSecondaire<Livre,{code, annéeParution}>

Hachage<{Livre},{ISBN}>

Livre

<<table>>

IndexSecondaire<Livre,{code, annéeParution}>

IndexSecondaire<Livre,{annéeParution}>

(97)

Méthode d ’accès

multidimensionnelle

 Ex: accès par titre, code, annéeParution et nomEditeur

– seule ou en combinaison

 Indexer toutes les combinaisons ?

 Un index pour chacune des colonnes

 Organisation multidimensionnelle

(98)

Maintenance des contraintes d ’intégrité

 Contrainte PRIMARY KEY(ISBN)

– hachage ou indexage sur ISBN

 Heuristique

– hachage ou indexage sur PRIMARY KEY et UNIQUE

– Oracle :

 index secondaire automatique

INSERT INTO Livre VALUES(…)

(99)

7.3.5 Sélection par intervalle

 Index sur titre

 Préfixe ~ intervalle

SELECT *

FROM Livre

WHERE titre = 'unPréfixe%'

Références

Documents relatifs

– Deux opérations de lecture ou d'écriture dans deux transactions différentes sont non permutables si elles portent sur la même donnée et au moins une des deux est

titre nomProducteur nomActeur La vie est belle Elda Ferri Roberto Benigni La vie est belle Elda Ferri Nicoletta Braschi La vie est belle Elda Ferri Giorgio Cantarini La vie est

Schémas (LDD), modules codés et

 Exigence de performance : Le temps d'attente de la validation de l'identificateur de l'utilisateur et de la vérification des conditions requises pour un

Lors d'un prêt ou d'un retour , l' identificateur d'utilisateur et l' identificateur de l'exemplaire peuvent être saisis en utilisant un lecteur optique ou manuellement...

Menu Edit  Include Pour inclure dans le diagramme des artefacts qui sont déjà dans le référentiel Menu View  Zoom In/ Zoom Out Pour changer la taille à l'écran. Menu Utilities

2 Sélection d'une ligne par jointure dans une organisation par index groupant ou hachage hétérogène (CLUSTER). 3 Sélection d'une ligne par hachage sur clé candidate (PRIMARY

IF fStatutExemplaire (:NEW.ID_EXEMPLAIRE) &lt;&gt; 'disponible' THEN RAISE exemplaireNonDisponible;.