Fondements des Bases de Données Frédéric Flouvat Université de la Nouvelle-Calédonie [email protected] Présentation de l'UE Volume horaire : • 14h de cours (7 séances), 16h de TD (8 séances) et 10h de TP (5 séances) • répartition cours/TD en fonction de l'avancement • TP pour appliquer une fois les notions abordées en cours et TD Evaluation en contrôles continus: • 2 TP notés -> 2 notes de CC • un CC à la fin de chaque chapitre -> 2 notes de CC Objectif : interrogations avancées et normalisation des bases de données • approfondir les connaissances pratiques (contraintes, programmation procédurale, vues, …) et théoriques (algèbre relationnel, dépendances et normalisation) 2 Plan du cours Chapitre 1: Manipuler les données • Rappels: modèle relationnel, algèbre relationnel et SQL • Programmation procédurale • Contrôler les transactions Chapitre 2: Définir et structurer les bases de données • Contraindre les données • Définir des vues des données • Normaliser leur structure 3 Chapitre 1: Manipuler les données Rappels Frédéric Flouvat (en partie dérivé du cours du Pr. Jeffrey Ullman, Stanford University) Université de la Nouvelle-Calédonie [email protected] Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Généralités Une Base de Données : ensemble structuré et organisé permettant le stockage de grandes quantités d’informations afin d'en faciliter l'exploitation. Un Système de Gestion de Bases de Données : comprend un ensemble de données liées (la bd) et un ensemble de programmes permettant la définition, la saisie, le stockage, le traitement, la modification, la diffusion et la protection de ces données. • • • • • • • Liens entre les données Cohérence des données Souplesse d’accès aux données Sécurité Partage des données Indépendance des données Performances 5 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Architecture ANSI/SPARC Niveau externe Groupe d’utilisateurs 1 Groupe d’utilisateurs 2 Vue 1 Vue 2 Groupe d’utilisateurs n … Vue n Schéma conceptuel Niveau conceptuel Niveau physique Schéma logique Représentation physique Base de Données 6 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL La démarche de conception Univers d’application Conceptuel Elaboration du schéma Entité-Association Logique Passage au schéma relationnel Physique Implémentation sur le SGBD 7 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Modèle relationnel Dans le modèle relationnel, les données sont structurées en relation, d'ordinaire représentées sous forme tabulaire. • Ex : Personnes nss nom prenom age 12 Ijo John 45 45 Mayer Solange 35 Une relation est définie sur un schéma de relation. Chaque ligne est appelée un tuple. Les noms des colonnes sont appelés attributs. • Ex : La relation Personnes est définie sur le schéma PERSONNES qui compte 4 attributs : schema(PERSONNES)={nss, nom, prenom, age} t = <12, Ijo, John, 45> est un tuple de cette relation (tPersonnes) 8 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Modèle relationnel Une base de données est un ensemble de relations ri sur Ri. Un schéma de base de données est un ensemble {R1, …, Rn} de schémas de relations. • Ex : Soit d={Personnes, Departements, Activites} une base de données. Personnes nss nom prenom age 12 Ijo John 45 45 Mayer Solange 35 Activites Departements dep adresse Sciences Nouville Lettres Magenta #nss #dep fonction 12 Sciences Prof 45 Sciences Vacataire 45 Lettres MdC 12 Eco Vacataire 9 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Définitions Soit A un attribut. On note DOM(A), le domaine de A i.e. l’ensemble des valeurs que peux prendre l’attribut A. • Ex : DOM(dep) = {Sciences, Lettres, Eco, Droit, SHS …} • Ex : DOM(age) = ensemble des entiers naturels Le domaine actif de A dans r noté ADOM(A,r), est l’ensemble des valeurs constantes prises par A dans r. • Ex : ADOM(dep,Activites) = {Sciences, Lettres, Eco} La projection d’un tuple t sur l’attribut A (resp. {A,B}) est notée t[A] (resp t[A,B]). • Ex : Soit t = <12, Ijo, John, 45> • t[nom] = <Ijo> et t[nom, prenom] = <Ijo, John> 10 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Différents types de langages LDD : Langage de Définition de Données • Schéma de la bd et des vues LMD : Langage de Manipulation de Données • Requêtes, mises à jour LCD : Langage de Contrôle des Données • Gestion des accès utilisateurs LCT : Langage de Contrôle des Transactions • Gestion des transactions 11 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Langages de requêtes relationnels Les langages de requêtes sont généralement déclaratifs i.e. on spécifie ce que la sortie doit contenir et non comment l’obtenir. Les SGBD relationnels fonctionnent en amont avec des langages procéduraux qui spécifient comment obtenir les résultats aux requêtes. • Déclaratif : {nss DOM(Activites) | (nss,dep,fonction)Activites, (dep,adresse)Departements, adresse=‘Carnot'} • Procédural : for each tuple t1=<n,d,f> in relation Activites do for each tuple t2=<d’,a> in relation Departements do if d=d’ and a=‘Carnot' then output n end end 12 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Langages de requêtes relationnels Le modèle relationnel supporte des langages de requêtes simples et puissants qui permettent beaucoup d’optimisation. Langages théoriques • Algèbre relationnelle : Langage procédural très utile pour représenter les plans d'exécution des requêtes. • Calcul relationnel : Langage déclaratif orienté utilisateur. • Datalog : Langage déclaratif à base de règles. Augmente le calcul relationnel avec des capacités d'inférence. Langages commerciaux • SQL : Les opérateurs s’inspirent des différents langages théoriques. 13 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Syntaxe générale d'une requête SQL SELECT FROM [WHERE [GROUP BY [HAVING [ORDER BY <liste des attributs à projeter ou *> <liste des tables> <critères de restriction>] <liste des attributs d’agrégation>] <critères de restriction sur les agrégats>] <liste des attributs de tri>] SELECT <liste des attributs à projeter ou *> FROM <liste des tables> [CONNECT BY PRIOR <critères de récursivité>] [START WITH <condition de départ>] 14 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Principes des langages de requêtes relationnels Elle est constituée d'un ensemble d'opérateurs algébriques : • π, σ, , , • Entrée : une ou deux relations (opérateurs unaires ou binaires) • Sortie : une relation Requête relationnelle : Composition d'un nombre fini d'opérateurs algébriques. Le résultat d'une requête est une relation. L'ordre d'évaluation des opérateurs est spécifié dans la requête (requête procédurale). L’algèbre relationnelle manipule des ensembles. 15 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Intérêts A la base de l’optimisation de requêtes : • Les SGBDR traduisent les requêtes formulées avec SQL en une requête interne construite avec les opérateurs algébriques, requête qui sera par la suite optimisée pour en générer un plan d’exécution équivalent. Tous les LMD sont construits à partir de ces opérateurs de base. • + généralement mise à jour de la bd et emploi d'expressions arithmétiques et de fonctions d'agrégation telles que cardinalité, somme, minimum, maximum et moyenne. 16 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Les opérateurs Opérateurs de base • • • • • Projection (π) Sélection (σ) Produit cartésien () Différence () Union () Opérateurs supplémentaires (non essentiels, mais très utiles) • • • • Intersection () Jointure (⋈) Division () Renommage (ρA→B) 17 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Projection Soient r une relation sur R et Y schema(R). La projection de r sur Y notée πY(r), est définie par : πY(r) = { t[Y] DOM(Y) | tr } Soit S le schéma de relation associé à πY(r). On a schema(S)=Y. • Ex : πnom(Personnes) = πnom,prenom(Personnes) = πdep(Activites) = dep nom nom prenom Ijo Ijo John Mayer Mayer Solange Sciences Lettres Eco 18 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Sélection Soient r une relation sur R et F une formule de sélection. La sélection des tuples de r par rapport à F notée σF(r), est définie par : σF(r) = { t r | t ⊨ F } Soit S le schéma de relation associé à σF(r). On a schema(S) = schema(R). • Ex : σfonction=‘Prof’(Activites) = nss dep fonction 12 Sciences Prof 19 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Sélection Une formule de sélection simple sur R est une expression de la forme : A = a ou A = B, où A, B schema(R) et a Dom(A). Une formule de sélection est une expression composée de formules de sélection simples connectées à l'aide des connecteurs logiques ,, et des parenthèses. Soit r une relation sur R, tr et F une formule de sélection. t satisfait F, noté t ⊨ F, est défini récursivement par : 1) 2) 3) 4) 5) 6) t ⊨ A = a si t[A] = a t ⊨ A = B si t[A] = t[B] t ⊨ F1F2 si t ⊨ F1 et t ⊨ F2 t ⊨ F1F2 si t ⊨ F1 ou t ⊨ F2 t ⊨ F si t ⊭ F t ⊨ (F) si t ⊨ F 20 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Opérateurs ensemblistes r1 Soient r1 et r2 deux relations sur R1 et R2. Union : r1 r2 = { t | t r1 ou t r2 }. Différence : r1 – r2 = { t | t r1 et t r2 }. r2 Intersection : r1 r2 = { t | t r1 et t r2 }. r1 r2 = • Ex : r1 r2 = r1 - r2 = A B C A B C A B C 1 2 3 1 2 3 1 1 1 1 1 1 1 2 2 1 2 2 2 2 2 A B C 1 2 3 1 1 1 1 2 2 A B C 2 2 2 1 1 1 21 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Opérateurs ensemblistes Propriétés : • σF(r) = r σF(r) • σF1F2(r) = σF1(r) σF2(r) • σF1F2(r) = σF1(r) σF2(r) Toutes ces opérations prennent comme entrées deux relations qui doivent être compatibles vis-à-vis de l’union. Soit S le schéma de relation associé à r1 r2 , r1 - r2 ou r1 r2. On a par convention schema(S) = schema(R1). 22 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Produit cartésien Soient r1 et r2 deux relations sur R1 et R2 avec schema(R1)schema(R2) = ø. Le produit cartésien r1 r2 est définie par : r1 r2 = { t | t1 r1 et t2 r2 tel que t[schema(R1)]= t1 et t[schema(R2)]= t2 } Soit S le schéma de relation associé à r1 r2. On a schema(S) = schema(R1)schema(R2). 23 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Produit cartésien r1 A B C 1 2 1 1 r2 D E 3 2 4 1 1 1 3 2 2 A B C D E • Ex : r1 r2 = 1 2 3 2 4 1 1 1 2 4 1 2 2 2 4 1 2 3 1 3 1 1 1 1 3 1 2 2 1 3 24 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Jointure Soient r1 et r2 deux relations sur R1 et R2 et F une formule de sélection. La jointure de r1 et r2 par rapport à F, notée r1 ⋈F r2, est définie par : r1 ⋈F r2 = σF(r1 r2) Soit S le schéma de relation associé à r1⋈F r2. On a schema(S) = schema(R1)schema(R2). • • • • Équi-jointure quand F est une égalité. Thêta-jointure quand F n’est pas une égalité (>,<,>=,<=,<>). Auto-jointure quand r1 = r2. Jointure naturelle quand équi-jointure sur tous les attributs communs à R1 et R2 + projection (pas utile d’écrire F). 25 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Jointure r1 Ex : r1 r2 = A B C D E 1 2 3 2 4 1 1 1 2 4 1 2 2 2 4 1 2 3 1 3 A B C 1 2 1 1 r2 D E 3 2 4 1 1 1 3 2 2 r1 ⋈A=D r2 = A B C D E 1 2 3 1 3 1 1 1 1 3 1 2 2 1 3 r1 ⋈A<D r2 = A B C D E 1 2 3 2 4 1 1 1 2 4 1 2 2 2 4 1 1 1 1 3 1 2 2 1 3 26 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Jointure naturelle r2 r1 A B C 2 2 2 1 1 1 Ex : A D E 1 2 1 r3 A B C 3 1 1 1 2 1 2 2 3 1 3 1 2 r1 ⋈ r2 = r 1 ⋈ r3 = r1 r3 r4 D E F 1 1 1 1 3 2 2 2 r 1 ⋈ r4 = r1 r4 A B C D E A B C A B C D E F 2 2 2 3 1 1 1 1 2 2 2 1 1 1 1 1 1 2 3 2 2 2 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 2 2 2 27 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Renommage Soient r une relation sur R, A schema(R) et B schema(R). Le renommage de A en B dans r noté ρA→B(r), est défini par : ρA→B(r) = { t | ur, t[schema(R) {B}] = u[schema(R) {A}] et t[B] = u[A]} Soit S le schéma de relation associé à ρA→B(r). On a schema(S) = (schema(R){A}){B}. • Ex : r1 ⋈ ρB→B’,C→C’(r3) = A B C B C’ ’ 1 1 1 1 1 1 1 1 2 3 28 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Division La division permet d'exprimer le quantificateur universel (). Exemple de requête : "Donner la liste des étudiants qui sont inscrits à tous les cours". Inscriptions etud cours 1 BD 1 RO 1 BI 2 RO Enseignements cours BD RO BI 29 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Division Soient r une relation sur R, avec schema(R) = XY, et s une relation sur S, avec schema(S) = Y. La division de r par s notée r s, est défini par : r s = { t[X] | tr et sπY(σF(r))} avec X={A1,..., Aq} et F =(A1=t[A1])…(Aq=t[Aq]) Soit schema(T) le schéma de relation associé à r s. On a schema(T) = X. 30 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Division La division n'est pas une opération essentielle car elle peut être exprimée à l'aide des opérateurs de projection, différence et produit cartésien. Pour calculer r s, il faut calculer toutes les valeurs de X dans r qui ne sont pas disqualifiées par des valeurs de Y dans s. Une valeur de X est disqualifiée si en lui rattachant une valeur de Y de s, le tuple obtenu sur XY n'appartient pas à r. • Valeurs disqualifiées de X : πx((πx(r) s) r) • r s = πx(r) valeurs disqualifiées de X r s = πx(r) πx((πx(r) s) r) 31 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Division Mod1 F3 cours c2 Ex : UNC Mod1 = etud Mod2 UNC cours etud cours 2 c1 1 c1 4 c3 1 c2 c4 1 c3 1 c4 2 c1 2 c2 3 c2 4 c2 4 c4 UNC F3 = UNC Mod2 = etud 1 cours etud 2 c2 1 3 4 32 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Propriétés σF(σF’(r)) = σF’(σF(r)) πX(πY(r)) = πXY(r) σF(πX(r)) = πX(σF(r)) σF(r ⋈ s) = σF(r) ⋈ s si F porte sur schema(R) πX(r ⋈ s) = πX(r) ⋈ πX(s) si schema(R) schema(S) = X (r1 r2) ⋈ r3 = (r1 ⋈ r3) (r2 ⋈ r3) Ex : Si schema(R1)=XY et schema(R2) =XZ, exprimer r1 ⋈ r2 avec , ρ, σ, π r1 ⋈ r2 = πXYZ(σX=X’(r1 ρX→X’(r2))) Ex : Si schema(R1)=schema(R2), exprimer r1 r2 avec r1 r2 = r1 (r1 r2) 33 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Représentation en arbre Une expression algébrique peut se représenter sous forme d’arbre : • La racine de l’arbre correspond à la requête • Les feuilles de l’arbre correspondent aux relations • Les nœuds de l’arbre correspondent aux opérateurs Q algébriques πX • Ex : Représenter Q = πX(σC1(r1 ⋈ r2) ⋈ (σc2(r3)r4)) ⋈ σC1 σc2 ⋈ r1 r2 r4 r3 34 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Arbres et optimisation de requêtes Femme c1 (nom) Cathy Julia Linda c2 (adr) Wé Nouméa Nouméa Homme c3 (nom) Bob Sam c4 (adr) Nouméa Koné Quels sont les couples possibles avec une femme de Nouméa et un homme de Koné ? πc1, c3 4 col, 2 lig σc2= "Nouméa" and c4= "Koné" x femme πc1 σc2= "Nouméa" 2 col, 2 lig homme 42 cases manipulées 1 col, 1 lig π c3 2 col, 2 lig 4 col, 6 lig 2 col, 3 lig x 1 col, 2 lig 2 col, 3 lig femme 2 col, 1 lig σc4= "Koné" 2 col, 2 lig homme 19 cases manipulées 35 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Extension de l’algèbre relationnelle Quatre nouveaux opérateurs: δ (delta) : élimine de la relation résultat les tuples en double. Extension de la théorie aux multi-ensembles τ (tau) : trie les tuples. γ (gamma) : groupe et agrège. Outerjoin : évite les "tuples incomplets" = les tuples qui ne sont liés/joins à aucun autre tuple. 36 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Elimination des doublons R1 := δ(R2). R1 est une copie de chaque tuple qui apparaissent dans R2 une ou plusieurs fois (une copie sans doublons donc). Exemple: R= ( δ(R) = A B) 1 3 1 2 4 2 A B 1 3 2 4 37 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Trier R1 := τL (R2). • L est une liste d’attributs de R2. R1 est la liste des tuples de R2 triés par rapport au premier attribut de L, puis par rapport au deuxième attribut, … • si plusieurs solutions sont possibles, en prend une arbitrairement τ est le seul opérateur n’ayant pas pour résultat un ensemble ou un multi-ensemble. • le résultat est une séquence de tuples Exemple: R= (A 1 3 5 B) 2 4 2 τ B (R) = [(5,2), (1,2), (3,4)] 38 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Opérateurs d’agrégation Les opérateurs d’agrégation ne sont pas des opérateurs de l’algèbre relationnelle. Ils sont appliqués sur une colonne d’une table et ont pour résultat une seule valeur. Exemple d’opérateurs: SUM, AVG, COUNT, MIN, et MAX. Exemple: R= (A B) 1 3 3 4 3 2 SUM(A) = 7 COUNT(A) = 3 MAX(B) = 4 AVG(B) = 3 39 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Opérateur de regroupement R1 := 1. 2. γ L (R2). L est une liste composées d’éléments de type: attributs (regroupement ). AGG(A), où AGG est un des opérateurs d’agrégation et A est un attribut. – Une flèche et un nouveau nom d’attribut renomme la composante. Fonctionnement de • L (R) Groupe R par rapport à tous les attributs de regroupement de L – • • γ forme un groupe pour chaque liste de valeur distincte pour les attributs de R Pour chaque groupe, calcule AGG(A) Chaque groupe est associé à un tuple dans la relation résultat – – avec pour attributs, les attributs de regroupement et les résultats des opérations d’agrégation 40 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Opérateur de regroupement Exemple: R= ( A 1 4 1 γ A,B,AVG(C)->X B 2 5 2 C 3 6 5 ) (R) = ?? Premièrement, regrouper R par rapport A et B : A B C 1 2 3 1 2 5 4 5 6 Puis, calculer la moyenne de C pour chaque groupe: A 1 4 B 2 5 X 4 6 41 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Jointure externe (Outerjoin) Supposons que l’on fasse R ⋈ C S. Un tuple de R qui n’est associé à aucun tuple de S par jointure est dit incomplet. • De la même manière pour un tuple de S. La jointure externe conserve les tuples incomplets dans la solution en leur associant la valeur NULL. 42 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Jointure externe (Outerjoin) Exemple: R= ( A 1 4 B) 2 5 S= ( B 2 6 C ) 3 7 (1,2) est associé par jointure à (2,3), mais les autres tuples sont incomplets R OUTERJOIN S = A 1 4 NULL B 2 5 6 C 3 NULL 7 43 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL MAINTENANT --- RETOUR AU SQL Chaque opération a un équivalent en SQL 44 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Jointures externe R OUTER JOIN S est l’instruction principale pour faire une jointure externe. Elle est complétée par: Uniquement 1. NATURAL devant OUTER (Optionnel). une des deux 2. ON <condition> après JOIN (Optionnel). 3. LEFT, RIGHT, ou FULL devant OUTER (Optionnel). LEFT = conserve les tuples incomplets de R seulement. RIGHT = conserve les tuples incomplets de S seulement. FULL = conserve les tuples incomplets des deux; valeur par défaut. Exemple: A partir de Sells(bar, beer, price) et Frequents(drinker ,bar), afficher tous les clients et les bières qu’ils peuvent consommer SELECT drinker, beer FROM Sells, Frequents RIGHT OUTER JOIN ON Sells.bar = Frequents.bar ; 45 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Agrégations SUM, AVG, COUNT, MIN, et MAX peuvent être appliqués à une colonne dans une clause SELECT afin d’appliquer l’agrégation sur cette colonne. Egalement, COUNT(*) pour compter le nombre de tuples. Exemple: A partir de Sells(bar, beer, price), trouver le prix moyen d’une Bud: SELECT AVG(price) FROM Sells WHERE beer = ’Bud’; 46 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Eliminer les doublons dans une Agrégation Utiliser DISTINCT à l’intérieur de l’agrégation. Exemple: Trouver le nombre de prix différents associés à la Bud: SELECT COUNT(DISTINCT price) FROM Sells WHERE beer = ’Bud’; 47 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Les NULL ignorés dans les Agrégations Les valeurs NULL ne contribuent jamais à une somme, une moyenne, ou un comptage, et ne peuvent jamais être le minimum ou le maximum d’une colonne. Mais s’il n’y a pas de valeurs non-NULL dans une colonne, alors le résultat de l’agrégation est NULL. • Exception: COUNT d’un ensemble vide retourne 0. Exemple: SELECT count(*) FROM Sells WHERE beer = ’Bud’; SELECT count(price) FROM Sells WHERE beer = ’Bud’; Le nombre de bars qui vendent de la Bud Le nombre de bars qui vendent de la Bud à un prix connu 48 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Groupement Après l’expression SELECT-FROM-WHERE, ajouter GROUP BY et une liste d’attributs. La relation qui résulte du SELECT-FROM-WHERE est groupées en accord avec les valeurs de tout ces attributs, et un opérateur d’agrégation est appliqué sur chaque groupe. Exemple: A partir de Sells(bar, beer, price), trouver ler prix moyen de chaque bière: SELECT beer, AVG(price) FROM Sells GROUP BY beer; beer Bud … AVG(price) 2.33 … 49 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Groupement Exemple: A partir de Sells(bar, beer, price) et Frequents(drinker,bar), trouver pour chaque client le prix moyen de la Bud au bar qu’ils fréquentent: SELECT drinker, AVG(price) FROM Frequent,Sells WHERE beer = ‘Bud’ AND Frequents.bar = Sells.bar GROUP BY drinker; Construit tous les tuples drinkerbar-price associés à la Bud Puis, les regroupent par clients 50 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Restriction sur le SELECT avec une Agrégation Si une agrégation est effectuée, alors chacun des éléments du SELECT doit être soit: 1. Une opération d’agrégation, ou 2. Un attribut utilisé au niveau d’un GROUP BY Exemple de requête interdite: • Il semble correcte de rechercher le bar qui vend les bières Bud les moins chères par la requête: SELECT bar, MIN(price) FROM Sells WHERE beer = ’Bud’; • Mais cette requête est interdite en SQL. 51 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Clauses HAVING HAVING <condition> peut suivre une clause GROUP B. Si tel est le cas, la condition est appliquée à chaque groupe, et les groupes ne satisfaisant pas la condition sont ignorés. Exemple: A partir de Sells(bar, beer, price) et Beers(name, manf), trouver le prix moyen des bières qui sont soient servies dans au moins trois bars ou sont fabriquées par Pete. ??? 52 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Clauses HAVING Exemple: Les groupes de bières avec au moins 3 bars non-NULL et aussi les groupes de bières avec pour fabricant Pete SELECT beer, AVG(price) FROM Sells GROUP BY beer HAVING COUNT(bar) >= 3 OR beer IN (SELECT name FROM Beers WHERE manf = ’Pete’’s’); Les bières fabriquées par Pete 53 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Restrictions sur les conditions du HAVING Tout doit être dans une sous-requête. A part les sous-requêtes, les conditions peuvent être sur des attributs uniquement si: 1. ce sont les attributs utilisés pour le regroupement, ou 2. s’ils sont agrégés (même condition que pour la clause SELECT lorsqu’elle est utilisée pour une agrégation). 54 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Modifications des relations d’une base de données Une commande de modification ne retourne pas de résultat (comme le fait une requête), mais change le contenu des relations. Trois types de modifications: 1. Insert : insertion d’un ou plusieurs tuples. 2. Delete : suppression d’un ou plusieurs tuples. 3. Update : mise à jours des valeurs d’un ou plusieurs tuples existants. 55 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Insertion Pour insérer un unique tuple: INSERT INTO <relation> VALUES ( <list of values> ); Attention: les valeurs doivent être dans le même ordre que les attributs de la relation et les types doivent correspondre. Exemple: Ajouter à Likes(drinker, beer) le fait que Sally aime les bières Bud. INSERT INTO Likes VALUES(’Sally’, ’Bud’); 56 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Spécifier les attributs de l’INSERT Il est possible d’ajouter au nom de la relation une liste d’attributs Deux raisons de faire ainsi: 1. l’ordre des attributs de la relation a été oublié. 2. il n’y a pas de valeurs pour tous les attributs, et nous voulons que le SGBD remplace ces valeurs manquantes par NULL ou par une valeur par défaut. Exemple: Une autre approche pour ajouter à Likes(drinker, beer) le fait que Sally aime les Bud : INSERT INTO Likes(beer, drinker) VALUES(’Bud’, ’Sally’); 57 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Ajouter des valeurs par défaut Dans la commande CREATE TABLE permettant de créer une table, il est possible de faire suivre la définition d’un attribut par DEFAULT et une valeur. Lorsqu’un tuple à insérer n’a pas de valeur pour cet attribut, la valeur par défaut est utilisée. Exemple: CREATE TABLE Drinkers ( name CHAR(30) PRIMARY KEY, addr CHAR(50) DEFAULT ’123 Sesame St.’, phone CHAR(16) ); 58 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Ajouter des valeurs par défaut Exemple : INSERT INTO Drinkers(name) VALUES(’Sally’); • relation résultat: name Sally address 123 Sesame St phone NULL 59 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Insertion de plusieurs tuples Il est possible d’insérer la totalité du résultat d’une requête dans une relation, en faisant: INSERT INTO <relation> ( <subquery> ); Exemple : En utilisant la relation Frequents(drinker, bar), insérer dans une nouvelle relation PotBuddies(name) contenant tous les amis potentiels de Sally, i.e. les clients qui fréquente au moins un des bars que fréquente Sally. 60 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Insertion de plusieurs tuples Exemple : les autres clients INSERT INTO PotBuddies (SELECT d2.drinker FROM Frequents d1, Frequents d2 WHERE d1.drinker = ’Sally’ AND d2.drinker <> ’Sally’ AND d1.bar = d2.bar ); les pairs de tuples de clients où le premier est Sally et le second est quelqu’un d’autre, et les bars sont les mêmes 61 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Suppression de tuples Pour supprimer les tuples d’une relation en fonction de conditions: DELETE FROM <relation> WHERE <condition>; Exemple: Supprimer de Likes(drinker, beer) le fait que Sally aime la Bud: DELETE FROM Likes WHERE drinker = ’Sally’ AND beer = ’Bud’; Supprimer tous les tuples d’une relation: DELETE FROM Likes; • Remarque: pas de clause WHERE. 62 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Problème de suppression Exemple: Supprimer de Beers(name,manf) toutes les bières pour lesquelles il y a une autre bière fournie par le même fabricant. DELETE FROM Beers b WHERE EXISTS ( SELECT name FROM Beers WHERE manf = b.manf AND name <> b.name); Bières faite par le même fabricant et ayant un nom différent du nom de la bière représenté par le tuple b. name name manf Bud Anheuser-Busch Bud lite Anheuser-Busch Man Peterson Man ? name manf Peterson manf Bud lite Anheuser-Busch Man Peterson 63 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Problème de suppression Exercice: exécution de la suppression • Supposons que Anheuser-Busch fait uniquement de la Bud et de la Bud Lite. • Supposons que le SGBD arrive au tuple b de la première Bud. • La sous-requête est non vide, à cause du tuple avec Bud Lite, donc le tuple b de la Bud est supprimé. • Maintenant, quand le tuple b devient le tuple avec Bud Lite, est-il aussi supprimé ? ➡ Réponse: le tuple avec Bud Lite est aussi supprimé Ceci est dû au fait que la suppression s’effectue en deux étapes: 1. marquer les tuples pour lesquels la condition du WHERE est satisfaite 2. supprimer les tuples marqués 64 Le modèle relationnel Algèbre relationnelle et SQL Modifications des données en SQL Mise à jour Pour changer la valeur de certains attributs dans certains tuples d’une relation: UPDATE <relation> SET <list of attribute assignments> WHERE <condition on tuples>; Exemple: Modifier le numéro de téléphone du client Fred à la valeur 555-1212: UPDATE Drinkers SET phone = ’555-1212’ WHERE name = ’Fred’; Fixer à $4 le prix maximum d’une bière: UPDATE Sells SET price = 4.00 WHERE price > 4.00; 65 Chapitre 1: Manipuler les données Programmation procédurale Frédéric Flouvat (dérivé du cours du Pr. Jeffrey Ullman, Stanford University et du cours du Pr. Christian Retoré, Université de Bordeaux) Université de la Nouvelle-Calédonie [email protected] 66 Premières procédures PSM Manipuler les requêtes SQL PL/pgSQL Le SQL dans de vrais programmes Pour l’instant, le SQL est utilisé comme interface générique pour faire des requêtes • un environnement où l’utilisateur est face à un terminal et fait des requêtes à une base de données. La réalité est différente: interagissent avec le SQL. des programmes conventionnels Les options possibles: • le code dans un langage spécifique est stocké dans la base de données (PSM, PL/SQL). • les instructions SQL sont englobées dans un langage hôte (p.ex. le C) et transformées/exécutées en ligne par un préprocesseur (Embedded SQL). • des outils de connections sont utilisés pour permettre à un langage conventionnel d’accéder à la base de données (p.ex. CLI, JDBC, PHP) 67 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Les Procédures Stockées PSM, ou “persistent stored modules,” permet de stocker des procédures comme des éléments du schéma de la base de données. • SQL/PSM un standard international (ISO) PSM = un mélange d’instructions conventionnelles (if, while, etc.) et de SQL. Permet de faire des choses que ne permet pas le SQL tout seul. Attention: en pratique, des implémentations légèrement différentes en fonction des éditeurs • p.ex. PL/SQL dans Oracle, PL/pgSQL dans PostgreSQL 68 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Structure de base d’une procedure PL/pgSQL CREATE [OR REPLACE] FUNCTION <name> (<arguments>) RETURNS <type> AS $$ DECLARE <optional declarations> BEGIN <PL/SQL statements> instructions END; obligatoires $$ LANGUAGE plpgsql; Les paramètres/arguments: • syntaxe nom mode type (différent de PSM), séparés par des virgules, avec mode égal à : – IN = variable en entrée, non modifiée par la procédure. – OUT = variable retournée en sortie de l’algorithme. – INOUT = les deux. Type de retour (RETURNS): mettre VOID pour une procédure Déclaration des variables locales (DECLARE): optionnelle Corps de la procédure (BEGIN … END;): séparer les instructions par des points virgules 69 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Exemple de procédure sockée PL/pgSQL Ecrivons une procédure avec deux paramètres b et p, et qui ajoute un tuple ayant bar = ’Joe’’s Bar’, beer = b, et price = p, à la relation Sells(bar, beer, price). • utilisée par Joe pour ajouter des bières à sa carte plus facilement. CREATE FUNCTION JoeMenu( b IN VARCHAR(10), p IN INTEGER ) les paramètres sont tous les RETURNS VOID AS $$ deux en lecture seule, i.e. BEGIN non modifiés INSERT INTO Sells VALUES (’Joe’’s Bar’, b, p); END; $$ LANGUAGE plpgsql; le corps --une seule insertion 70 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Invoquer des Procédures PL/pgSQL SELECT * FROM <name>(<arguments>) ; ou SELECT <name>(<arguments>) ; Exemple: SELECT JoeMenu(’Moosedrool’, 5.00); Les fonctions peuvent être utilisées dans des expressions SQL, à condition que le type de la valeur retournée soit approprié. • Attention au type de retour RECORD qui n'a pas de structure prédéfinie et qui peut donc nécessiter un transtypage (cast) pour pouvoir être utilisé dans une autre expression SQL 71 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables PL/pgSQL Déclarations et Affectations Déclarer une variable/un paramètre: <name> <type> • Les types SQL. • De nouveaux types: – p.ex. type composite CREATE TYPE element_inventaire AS ( nom text, id_fournisseur integer, prix numeric ); Affecter une valeur: <variable> := <expression>; • Exemple: b := 'Bud'; 72 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Les variables de type attribut et variables de type tuple PL/pgSQL permet à une variable d’avoir le même type qu'un attribut d'une relation ou la même structure qu’un tuple de ses tuples. • Attention: ne fonctionne pas avec les types composites (CREATE TYPE) x R.a%TYPE donne a x le même type que l'attribut a de R. x R%ROWTYPE donne à x le type des tuples de R. • x.a donne la valeur de l’attribut a du tuple x. Exemple: Reprendre JoeMenu(b,p) en utilisant Sells.beer et Sells.price. CREATE FUNCTION JoeMenu( b IN "Sells".beer%TYPE, p IN "Sells".price%TYPE) RETURNS VOID AS $$ BEGIN INSERT INTO Sells VALUES (’Joe’’s Bar’, b, p); END; $$ LANGUAGE plpgsql; 73 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Instructions conditionnelles IF et CASE Les IF • IF <condition> THEN <statement(s)> END IF; • IF . . . THEN . . . ELSE . . . END IF; • IF … THEN … ELSIF … … THEN … ELSE … END IF; • Les CASE • CASE <search-expression> WHEN <expression> [, <expression> [ ... ]] THEN <statement(s)> WHEN … THEN … ELSE ... END CASE; • CASE WHEN <boolean-expression> THEN <statement(s)> ... END CASE; 74 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Exemple: IF Classer les bars en function de leur nombre de clients en utilisant la relation Frequents(drinker,bar). • <100 clients: ‘unpopular’. • 100-199 clients: ‘average’. • >= 200 clients: ‘popular’. La fonction Rate(b) classe le bar b. CREATE FUNCTION Rate( b IN CHAR(20) ) RETURNS CHAR(10) AS $$ DECLARE nombre de clients du bar b cust INTEGER; BEGIN SELECT COUNT(*) INTO cust FROM "Frequents" WHERE bar = b; IF cust < 100 THEN RETURN ’unpopular’ ; ELSIF cust < 200 THEN RETURN ’average’; IF imbriqués ELSE RETURN ’popular’; END IF; retourne la valeur ici et non RETURN; END; lors des autres RETURN $$ LANGUAGE plpgsql; 75 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Les boucles Forme basique: [<loop label>] LOOP <statements> END LOOP [<loop name>]; Interrompre une boucle: EXIT [<loop label>] [ WHEN <condition> ] Exemple: loop1 LOOP ... EXIT loop1; ... END LOOP loop1; si cette instruction est exécutée fin de la boucle 76 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Les boucles [<while label>] WHILE <condition> LOOP <statements> END LOOP [<while label>] ; [<for label>] FOR <variable> IN [ REVERSE ] <expression> .. <expression> [ BY <expression> ] LOOP <statements> END LOOP [<for label>]; Exemple: FOR i IN 1 .. 10 BY 2 LOOP … END LOOP; 77 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Exécuter des requêtes dans une procédure Les requêtes générales SELECT-FROM-WHERE ne peuvent pas être exécutées directement. Seules les requêtes ne retournant aucun résultat peuvent être directement invoquées (p.ex. INSERT). Il y a trois principales méthodes pour manipuler le résultat d’une requête SELECT: • SELECT . . . INTO… • Parcourir le résultat de la requête dans une boucle FOR. • Les curseurs. 78 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables SELECT . . . INTO Un moyen de récupérer la valeur d’une requête qui retourne un unique tuple est d’utiliser INTO <variable> après la clause SELECT. Exemple: SELECT price INTO p FROM Sells WHERE bar = ’Joe’’s Bar’ AND beer = ’Bud’; 79 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables FOR. . . IN Un moyen de récupérer la valeur d’une requête qui retourne un ensemble de tuples est d’utiliser une boucle FOR … IN… Exemple: CREATE OR REPLACE FUNCTION JoeGouge() RETURNS VOID AS $$ DECLARE r RECORD; BEGIN FOR r IN SELECT beer, price FROM "Sells" WHERE bar='Joe"s Bar' LOOP IF r.price < 3.00 THEN UPDATE "Sells" SET price = r.price+ 1.00 WHERE bar = ’Joe’’s Bar’ AND beer = r.beer; END IF; END LOOP; END; $$ LANGUAGE plpgsql; 80 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Les curseurs Un curseur est principalement une variable de type tuple qui stocke tous les tuples résultats d’une requête. Déclaration d’un curseur en PL/pgSQL : DECLARE <name> CURSOR [(<arguments>)] FOR <query>; Exemple: DECLARE c CURSOR (b varchar) FOR SELECT * FROM Sells WHERE beer=b; Utilisation d’un curseur : • initialisation du curseur: OPEN <name>[(<arguments>)] ; – la requête est évaluée, et le curseur pointe sur le premier tuple du résultat. • libération du curseur: CLOSE <name>; 81 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Parcourir les tuples d’un Curseur Pour accéder au tuple suivant du curseur c, utiliser la commande: FETCH c INTO x1, x2,…,xn ; • les x sont des variables référençant chaque composant du tuple stocké dans c. • c est déplacé automatiquement au prochain tuple. Sortir d’une boucle d’un curseur • l’utilisation classique d’un curseur est de créer une boucle avec FETCH, et de faire un traitement pour chaque tuple parcouru. • mais comment sortir de la boucle quand tous les tuples ont été traités? EXIT WHEN NOT FOUND 82 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Exemple: Curseur en PL/pgSQL (déclaration) La procédure JoeGouge() utilise un curseur pour parcourir les ventes de Joe’s-Bar dans Sells(bar, beer, price), et augmente de $1 le prix des bières initialement vendue en dessous de $3 chez Joe’s Bar. Utilisé pour stocker les pairs beer-price lors du parcours du curseur CREATE FUNCTION JoeGouge() RETURNS VOID AS $$ DECLARE theBeer "Sells".beer%TYPE; thePrice "Sells".price%TYPE; c CURSOR FOR SELECT beer, price FROM "Sells" WHERE bar = ’Joe’’s Bar’; Retourne le menu de Joe 83 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Exemple: Curseur en PL/pgSQL (corps de la procédure) BEGIN OPEN c; LOOP condition d’arrêt de la FETCH c INTO theBeer, thePrice; boucle EXIT WHEN NOT FOUND; IF thePrice < 3.00 THEN UPDATE "Sells" SET price = thePrice + 1.00 WHERE bar = ’Joe’’s Bar’ AND beer = theBeer; END IF; END LOOP; Si Joe vend une bière moins $3, augmenter CLOSE c; son prix de $1 à Joe’s Bar. END; $$ LANGUAGE plpgsql; 84 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Retourner un ensemble de valeurs (Déclaration) Deux options principalement pour déclarer le type de retour de la fonction: • Déclarer … RETURNS SETOF <sometype> … • Déclarer … TABLE( <col1> <type1>, <col2> <type2> … ) … Déclaration: RETURNS SETOF • possibilité de retourner un ensemble de valeurs simples – p.ex. RETURNS SETOF integer • possibilité de retourner un ensemble de tuples en créant un nouveau type composite (ou en faisant référence à un type composite existant) – p.ex. CREATE TYPE nomprenom AS ( nom VARCHAR(20), prenom VARCHAR(30) ) ; CREATE FUNCTION clients() RETURNS SETOF nomprenom AS $$ … 85 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Retourner un ensemble de valeurs (Déclaration) Déclaration: TABLE( <col1> <type1>, <col2> <type2> … ) • syntaxe proche de la norme SQL/PSM • facilité d'interprétation • possibilité de retourner un ensemble de valeurs simples ou un ensemble de tuples • mais interdiction d'utiliser des paramètres en sortie (mode OUT) – p.ex. CREATE FUNCTION clients() RETURNS TABLE( nom VARCHAR(20), prenom VARCHAR(30) ) AS $$ … 86 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Retourner un ensemble de valeurs (Invocation) Deux options pour retourner des résultats dans le corps de la fonction: • RETURN QUERY <SQLquery> ; • RETURN NEXT [<expression>] ; Retourner : RETURN QUERY • compatible RETURNS SETOF et RETURNS TABLE • retourne le résultat d'une requête • possibilité de l'utiliser plusieurs fois – dans ce cas, chaque ensemble est ajouté à la suite de l'autre • résultat final uniquement retourné à la fin de la procédure ou au moment de l'appel RETURN; 87 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Retourner un ensemble de valeurs (Invocation) Exemple: RETURNS TABLE et RETURN QUERY CREATE OR REPLACE FUNCTION BarSallyJo () RETURNS TABLE( bar TEXT, name VARCHAR(30) ) AS $$ BEGIN … RETURN QUERY SELECT bar, drinker FROM "Frequents" WHERE drinker = 'Sally'; … RETURN QUERY SELECT bar, drinker FROM "Frequents" WHERE drinker = 'Jo'; … RETURN; END; $$ LANGUAGE plpgsql; 88 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Retourner un ensemble de valeurs (Invocation) Retourner : RETURN NEXT • enregistre une valeur/tuple à la fois dans l'ensemble des solutions • généralement invoqué dans une boucle • son utilisation dépend du type de retour de la fonction: Si RETURNS SETOF <sometype> alors RETURN NEXT <expression>; – <expression> est classiquement une variable du type associé au SETOF Si RETURNS TABLE( <col1> <type1>, <col2> <type2> … ) alors RETURN NEXT; – <col1>, <col2> … sont utilisées et initialisées comme des variables dans le corps de la procédure – chaque RETURN NEXT; enregistre dans l'ensemble des résultats un tuple initialisé à partir des valeurs en cours pour <col1>, <col2> … • résultat final uniquement retourné à la fin de la procédure ou au moment de l'appel RETURN; 89 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Retourner un ensemble de valeurs (Invocation) Exemple: RETURNS TABLE et RETURN NEXT; CREATE OR REPLACE FUNCTION BarSallyJo () RETURNS TABLE( bar TEXT, name VARCHAR(30) ) AS $$ BEGIN FOR bar, name IN SELECT bar, drinker FROM "Frequents" WHERE drinker = 'Sally' LOOP RETURN NEXT; END LOOP; FOR bar, name IN SELECT bar, drinker FROM "Frequents" WHERE drinker = 'Jo’ LOOP RETURN NEXT ; END LOOP; RETURN; END; $$ LANGUAGE plpgsql; 90 Persistent Stored Modules Syntaxe de base PL/pgSQL Manipuler des requêtes SQL et retourner des tables Retourner un ensemble de valeurs (Invocation) Exemple: RETURNS SETOF et RETURN NEXT; CREATE TYPE infobar AS ( bar TEXT, name VARCHAR(30) ); CREATE OR REPLACE FUNCTION BarSallyJo () RETURNS SETOF infobar AS $$ DECLARE r infobar; BEGIN FOR r IN SELECT bar, drinker FROM "Frequents" WHERE drinker = 'Sally' LOOP RETURN NEXT r ; END LOOP; … RETURN; END; $$ LANGUAGE plpgsql; 91 Chapitre 1: Manipuler les données Contrôler les transactions Université de la Nouvelle-Calédonie [email protected] Quelques références bibliographiques Documentation PostgreSQL 9.4, Chapitre 13. "Contrôle d'accès simultané" Livre "Database Management Systems", Raghu Ramakrishnan et Johannes Gehrke. "Database Systems: The Complete Book", Pr. Jeffrey Ullman, Stanford University "PostgreSQL Concurrency with MVCC", Heroku dev center "Transaction Processing in PostgreSQL" de Tom Lane, Great Bridge "Bases de données: Aspects système", Philippe Rigaux, Université Paris-Dauphine "Bases de données avancées", Jacques Le Maitre, Université du Sud Toulon-Var "Conception des bases de données", Stéphane Crozat, UTC 93 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Rappel Une bases de données est un ensemble de données • structurées • persistantes • cohérentes Cohérence garantie par des contraintes d'intégrités (contraintes de domaine, intégrité référentielles, dépendances fonctionnelles …) • cf "Contraindre les données", chapitre 2 Mais cohérence peut être remise en cause par: • Défaillances du système • Accès concurrents 94 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Pourquoi des accès concurrents ? Les systèmes de gestion de bases de données sont généralement utilisés par plusieurs utilisateurs et/ou processus à la fois. • Interrogations et modifications. Toutes ces opérations arrivent dans un certain ordre au SGBD qui les met en file d'attente pour traitement ("Scheduler") schéma issu du cours de Philippe Rigaux, Université Paris-Dauphine Exemple: • Deux personnes titulaires d’un compte commun retirent au même moment $100 dans deux distributeurs de billets différents. Le SGBD doit alors s’assurer que les deux retraits sont appliqués correctement au compte sous-jacent. 95 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Exemple: Transfert entre 2 comptes Transfert(A,B,M) Begin varA := Read(A) varA := varA + M Write(A,varA) varB := Read(B) varB := varB - M Write(B,varB) Commit A= 1500 et B=2000 Le guichet 1 exécute T1 : • Transfert(A,B,100) Le guichet 2 exécute T2 : • Transfert(A,B,-200) Si exécution à la suite (i.e. en série), pas de problème T1 -- A=1600 B=1900 T2 -- A=1300 B=2200 OU T2 -- A=1400 B=2100 T1 -- A=1400 B=2100 96 Transactions ACID & SQL Introduction aux accès concurrents Contrôle de la concurrence dans PostgreSQL Exemple: Transfert entre 2 comptes Transfert(A,B,M) Begin varA := Read(A) varA := varA + M Write(A,varA) varB := Read(B) varB := varB - M Write(B,varB) Commit Si exécution "entrelacée", problèmes possibles T1: R(A) T2: R(A) T2: W(A) T1: W(A) T1: R(B) T2: R(B) T1: W(B) T2: W(B) --------- A=1500 A=1500 A=1300 A=1600 B=2000 B=2000 B=1900 B=2200 A= 1600 et B= 2200 !!! 97 Transactions ACID & SQL Introduction aux accès concurrents Contrôle de la concurrence dans PostgreSQL Les problèmes liés aux accès concurrents Perte de mise à jour T1 T2 BD A=10 Read(A) Lectures incohérentes Read(A) T1 A=A+10 Write(A) T2 A = 20 A=A+50 BD A=120 B=80 Read(A) A=A-50 Write(A) A = 60 Write(A) A = 70 Read(A) Read(B) display A+B (affiche 150) Read(B) B=B+50 Write(B) B = 130 98 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Les problèmes liés aux accès concurrents T1 Lectures non reproductibles T2 BD A=10 Read(A) (lit 10) A=20 Write(A) A = 20 Read(A) (lit 20) Objets fantômes • la transaction ré-exécute une requête renvoyant un ensemble de lignes satisfaisant une condition de recherche et trouve que l'ensemble des lignes satisfaisant la condition a changé du fait d'une autre transaction récemment validée. T1 T2 BD Clients ={} INSERT INTO "Clients"(name) VALUES ('Bob'); Clients = {<'Bob', …>} SELECT COUNT(name) FROM "Clients"; (résultat 0) SELECT COUNT(name) FROM "Clients"; (résultat 1) 99 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Les transactions en Base de Données Transaction = ensemble d'instructions dont le résultat sera visible au reste du système d'un seul bloc si la transaction est validée (commit), ou pas du tout visible si elle est annulée (abort) Exemples: réservation d’une place d’avion, passer une commande sur un catalogue en ligne, … Hypothèses: • Les transactions interagissent entre elles uniquement via des lectures et des écritures dans la base de données. – pas de messages échangés • Une base de données est une collection fixe d'objets indépendants. 100 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Transactions et SQL Définir une transaction Begin; <instructions SQL> COMMIT; L’instruction SQL COMMIT valide une transaction. • Ses modifications sont maintenant permanentes dans la base de données. • Attention mode Autocommit: valide automatiquement toutes les instructions – dans PostgreSQL, les requêtes "isolées" sont par défaut validées automatiquement L’instruction SQL ROLLBACK implique aussi la fin d’une transaction, mais en l’annulant. • Aucun effet sur la base de données. • Une erreur comme une division par zéro ou une violation de contraintes peut également provoquer un rollback, même si le programmeur ne l‘a pas déclenché explicitement. 101 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Propriétés ACID Cohérence globale des données garantie par un certain nombre de propriétés sur les transactions Les transactions ACID sont: • Atomiques : La transaction est appliquée intégralement ou pas du tout. • Cohérentes : Les contraintes de la base de données sont préservées et les données sont cohérentes pour l'application. • Isolées : Une transaction ne doit jamais voir les résultats intermédiaires des autres transactions (comme si elle était là seule à être exécutée). • Durables : Dès qu’une transaction est validée, le système doit assurer que ses effets ne seront jamais perdus, même en cas de panne. 102 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Garantir Atomicité & Durabilité des transactions La des transactions est garantie par l’instruction SQL COMMIT • car une fois la transaction validée par un commit, le SGBD garantie que ses modifications seront permanentes dans la base de données (même après une panne) L' des transactions est garantie par l’instruction SQL ROLLBACK • car une fois la transaction annulée par un rollback, toutes ses opérations le sont aussi (tout ou rien) Rendu possible grâce à l'utilisation de journaux (fichiers) 103 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Garantir la Cohérence des transactions Garantie par le système via les contraintes d'intégrités associées au schéma • Clés primaires, clés étrangères, triggers, … Garantie par le développeur en utilisant correctement les propriétés des transactions de façon à prendre en compte les spécificités de l'application • Bonne utilisation des commit/rollback, définition du bon niveau d'isolation, … • Exemple des réservations dans une compagnie aérienne: – données cohérentes si le nombre de places occupées est le même que le nombre de places réservées difficile via des contraintes si niveau d'isolation trop faible ou mauvaise utilisation des commit/rollback, possibilité d'entrelacement des transactions (et donc d'incohérences) • comme pour le virement entre deux comptes bancaires 104 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Garantir l'Isolation des transactions Possibilité en SQL de définir le niveau d'isolation d'une transaction • p.ex. dans PostgreSQL, SET TRANSACTION ISOLATION LEVEL <level>; où <level> = 1. SERIALIZABLE 2. REPEATABLE READ 3. READ COMMITTED 4. READ UNCOMMITTED Garantir l'Isolation en utilisant le mode SERIALIZABLE • Isolation totale des transactions, i.e. les transactions s'exécutent indépendamment les unes des autres comme si elles étaient exécutées en série Problème: très "coûteux" Possibilité d'améliorer l'efficacité en abaissant le niveau d'isolation, mais attention à bien étudier les besoins de l'application … 105 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Les différents niveaux d'isolation SQL READ UNCOMMITED = lecture de données non validées • La transaction peut voir toutes les données de la base de données, même si elles ont été écrites par une transaction non validées. ++ pas de perte de mise à jour −−possibilité de lectures incohérentes, de lectures non reproductibles, et objets fantômes READ COMMITED = lecture de données validées • La transaction ne peut voir que les données validées, mais pas nécessairement les mêmes données à chaque fois. ++ pas de perte de mise à jour, pas de lectures incohérentes −−possibilité de lectures non reproductibles, et objets fantômes 106 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Les différents niveaux d'isolation SQL REPEATABLE READ = lecture répétée • La transaction ne peut voir que les données validées, mais si les données sont lues à plusieurs reprises dans la même transaction, alors toutes les informations vues la première fois sont également vues la seconde fois. – données vues = données première lecture + données actuellement validées Attention: la seconde lecture et celles suivantes peuvent voir plus de tuples que ce qu’il y a réellement dans la base de données. ++pas de perte de mise à jour, pas de lectures incohérentes, pas de lectures non reproductibles −−possibilité d'avoir des objets fantômes SERIALIZABLE = lecture en série • La transaction ne peut voir que les données qui sont validées lorsqu'elle débute ++ pas de perte de mise à jour, pas de lectures incohérentes, pas de lectures non reproductibles, et pas d'objets fantômes 107 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Ces différents niveaux dans PostgreSQL PostgreSQL READ UNCOMMITED = PostgreSQL READ COMMITED PostgreSQL READ COMMITED (niveau par défaut) identique à la norme SQL PostgreSQL REPEATABLE READ plus stricte que dans la norme SQL • La transaction ne peut voir que les données validées au début de la transaction – identique à SERIALIZABLE • La transaction peut être mise en attente et annulée en cas d'échec de sérialisation PostgreSQL SERIALIZABLE identique à la norme SQL • Le SGBD analyse d'abord si la requête est sérialisable et déclenche une erreur s'il détecte un problème 108 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Lectures et modifications concurrentes dans PostgreSQL Cas des lectures : la transaction lit des données en cours d'utilisation dans d'autres transactions • Les lecteurs ne bloquent pas ceux qui écrivent et inversement • Seules les données visibles par la transaction changent en fonction de son niveau d'isolation Cas des modifications : la transaction essaye de modifier des données modifiées dans d'autres transactions T1 • Read commited : Begin La transaction va attendre si une autre transaction est en train de modifier un tuple qu'elle doit aussi modifier T2 (READ COMMITED) Begin modifier tuple t ---------------modifier tuple t attente COMMIT ------modifier tuple t COMMIT 109 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Lectures et modifications concurrentes dans PostgreSQL T1 Begin Cas des modifications (suite) • Serializable : La transaction n'est pas exécutée et une erreur est déclenchée modifier tuple t ---------- T2 (SERIALIZABLE) analyse sérialisation -> tentative modification tuple t -> ERROR: could not serialize access due to concurrent update COMMIT T1 Begin T2 (REPEATABLE READ) Begin • Repeatable read : La transaction attend le résultat de l'autre transaction pour déclencher une erreur ou pour effectuer la modification modifier ---------tuple t ------modifier tuple t attente COMMIT ou ROLLBACK ------ Si COMMIT T1 : ERROR: could not serialize access due to concurrent update Si ROLLBACK T1 : modifier tuple t COMMIT 110 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Remarque : Isolation sérialisable et vrai sérialisation Définition "mathématique" d’exécution sérialisable: toute paire de transactions concurrentes validée avec succès apparaîtra comme ayant été exécutée en série, l'une après l'autre -- bien que celle survenant en premier n'est pas prévisible L’ordre d’exécution réel des transactions ne change pas le résultat Isolation sérialisable de PostgreSQL ne respecte pas totalement cette définition • Evite les comportements non désirables précédents • Mais le résultat peut changer en fonction de l’ordre d’exécution 111 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Remarque : Isolation sérialisable et vrai sérialisation Exemple: classe valeur 1 10 1 20 2 100 2 200 Transaction A: Begin; SELECT SUM(valeur) into sommeA FROM ma_table WHERE classe = 1; INSERT INTO ma_table value(2,sommeA); COMMIT; Transaction B: Begin; SELECT SUM(valeur) into sommeB FROM ma_table WHERE classe = 2; INSERT INTO ma_table value(1,sommeB); COMMIT; • si A exécuté avant : sommeB = 330 • si B exécuté avant : sommeB = 300 Pas réellement sérialisable Solution pour garantir une vrai sérialisation: système de verrous explicites des ressources • mais complexe à mettre en place et très coûteux • PostgreSQL le permet (cf chapitre 13.3 Verrouillage explicite) 112 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Implémentation de ces mécanismes par le SGBD Différentes stratégies mises en place en interne par les SGBD pour garantir la cohérence et les propriétés ACID des transactions • Verrouillage: une transaction verrouille certaines données qu'elle lit ou écrit pour interdire aux autres d'y accéder – verrouiller un tuple, une table, … inconvénient: dégrade les performances • Versionnement: conserver plusieurs versions des données – p.ex. image avant mise à jour et image après avantage: ne bloque pas les lectures/écritures inconvénient: occupe plus d'espace PostgreSQL utilise un contrôle de concurrence multi-versions (MVCC ou Multi-version Concurrency Control) 113 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Multi-Version Concurrency Control MVCC Les transactions sont numérotées par ordre chronologique Plusieurs versions de chaque tuple sont conservées • chaque version est associée au numéro de la transaction l'ayant créée ou modifiée (insert, update ou delete) • PostgreSQL stocke aussi l'état de la transaction (validée, en cours ou annulée) En fonction du niveau d'isolation de la transaction et des opérations réalisées, PostgreSQL accède aux bonnes informations et effectue les traitements adaptés 114 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Multi-Version Concurrency Control MVCC Exemple simplifié : • Soit la transaction 10 en mode SERIALIZABLE qui lit les données a, b, c, d, e, f et g • Soit les transactions 7 et 8 dans l'état "validé" • La valeur lue pour c par la transaction 10 est celle associée à la transaction 8 • La valeur lue pour e par la transaction 10 est celle associée la transaction 7 schéma issu du cours de Jacques Le Maitre, Université Sud Toulon-Var 115 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Où sont stockées ces versions ? Dans le journal des transactions • Journal = fichier système qui stocke (p.ex. sur disque dur) tout ce qui passe dans le système, i.e. un historique persistant • Il est indispensable pour la validation, l'annulation, la gestion des accès concurrents mais aussi pour la reprise après panne 3 fichiers dans PostgreSQL : • fichier pg_log pour les activités de la base de données – p.ex. messages d'erreurs, requêtes, messages de démarrage/arrêt • fichier pg_xlog pour stocker une image des données manipulées dans les transactions récentes • fichier pg_clog pour l'état des transactions (validée, annulée, en cours) 116 Introduction aux accès concurrents Transactions ACID & SQL Contrôle de la concurrence dans PostgreSQL Les limites du MVCC Nécessité de maintenir des tuples potentiellement obsolètes • En réalité, UPDATE créé un nouveau tuple et DELETE ne le supprime pas vraiment (il est simplement marqué comme étant supprimé) • Certains tuples vont être conservés alors qu'ils ne peuvent plus être utilisés dans des transactions futures Les identifiants des transactions ne peuvent dépasser une certaine valeur maximale • Identifiants sont des entiers 32 bits "Pas plus" de 4 milliards de transactions Solution: faire des nettoyages réguliers de la base de données (instruction VACUUM) • Nettoyage automatique configurable (AUTOVACUUM) 117 Chapitre 2: Définir et structurer les bases de données Contraindre les données Frédéric Flouvat (dérivé du cours du Pr. Jeffrey Ullman, Stanford University) Université de la Nouvelle-Calédonie [email protected] 118 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Contraintes et Triggers Une contrainte est une règle que doivent respecter les données et que le SGBD doit imposer. • Exemple: contraintes de clés. Les Triggers sont uniquement exécutés lorsqu’une condition prédéfinie apparaît, p.ex. insertion d’un tuple. • Plus facile à implémenter que des contraintes complexes. 119 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les types de contraintes Les clés (primaires). Les clés étrangères, ou contraintes d’intégrité référentielle. Les contraintes de valeurs. • contraintes de valeurs sur un attribut particulier. Les contraintes sur les tuples. • relations entre composants. Les assertions: n’importe quelle expression SQL booléenne. • contraintes booléennes sur les objets de la base de données. 120 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les clés primaires Clé primaire composé d’un seul attribut: • Mettre PRIMARY KEY ou UNIQUE après le type dans la déclaration de l’attribut. CREATE TABLE Beers ( name CHAR(20) UNIQUE, manf CHAR(20) ); Différence PRIMARY KEY vs. UNIQUE • il peut y avoir une seule PRIMARY KEY pour une relation, mais plusieurs attributs UNIQUE. • Aucun attribut d’une PRIMARY KEY ne peut avoir la NULL pour un tuple, alors que les attributs déclarés UNIQUE peuvent prendre la valeur NULL et ceci plusieurs fois. 121 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les clés primaires Clé primaire composée de plusieurs attributs: • Mettre PRIMARY KEY(<liste d’attributs>) après le dernier attribut. CREATE TABLE Sells ( bar CHAR(20), beer VARCHAR(20), price REAL, PRIMARY KEY (bar, beer) ); 122 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les clés étrangères Les valeurs prises par les attributs de la clé étrangère d’une relation doivent aussi apparaître ensemble au niveau des attributs d’une autre relation. • une clé étrangère est clé primaire dans une autre relation. • attributs utilisés pour les jointures. Exemple: Dans Sells(bar, beer, price), les valeurs pour l’attribut beer apparaissent aussi toutes au niveau de l’attribut name de la relation Beers(name, manf). name bar beer price 5 manf Bud Anheuser-Busch Bud lite Anheuser-Busch Pete Bud Pete Bud lite 2.22 Man Peterson Kend Man 17 Al 1 123 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Définir des clés étrangères Utiliser le mot clé REFERENCES, au choix : 1. après un attribut (pour une clé composé d’un attribut). 2. comme un élément de l‘expression: FOREIGN KEY (<list of attributes>) REFERENCES <relation> (<attributes>) Les attributs référencés doivent être déclarés PRIMARY KEY ou UNIQUE. 124 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Définir des clés étrangères Exemple avec un attribut: CREATE TABLE Beers ( name CHAR(20) PRIMARY KEY, manf CHAR(20) ); CREATE TABLE Sells ( bar CHAR(20), beer CHAR(20) REFERENCES Beers(name), price REAL ); 125 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Définir des clés étrangères Exemple en tant qu’élément du schéma de la relation: CREATE TABLE Beers ( name CHAR(20) PRIMARY KEY, manf CHAR(20) ); CREATE TABLE Sells ( bar CHAR(20), beer CHAR(20), price REAL, FOREIGN KEY(beer) REFERENCES ); Beers(name) 126 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Violation des contraintes de clé étrangère Si une contraint de clé étrangère est définie de la relation R vers la relation S, deux violations de cette contrainte sont possibles: 1. Une insertion ou une mise à jour de R introduit des valeurs qui n’existent pas dans S. name bar 1. beer price manf Bud Anheuser-Busch Pete Bud 5 Bud lite Anheuser-Busch Pete Bud lite 2.22 Man Peterson Kend Nber 1 17 Al Une suppression ou mise à jour de S entraîne que des tuples de R deviennent “incomplets”. name bar beer price manf Bud Anheuser-Busch Pete Bud 5 Bud lite Anheuser-Busch Pete Bud lite 2.22 Man Peterson Kend Man 1 17 Al 127 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Actions à prendre pour imposer les contraintes de clé étrangère Exemple: • Supposons que R = Sells, S = Beers. • Une insertion ou une mise à jour de Sells doit être rejetée lorsqu’elle implique la vente d’une bière n’existant pas. • Une suppression ou une mise à jour de Beers qui enlève une valeur de bière utilisée dans certains tuples de Sells peut être traitée de trois façons. 1. 2. 3. Default : rejet de la modification. Cascade : faire les mêmes modifications dans Sells. • bière supprimée : supprime des tuples de Sells. • bière mise à jour: change des valeurs dans Sells. Set NULL : remplace la bière par NULL. 128 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Actions à prendre pour imposer les contraintes de clé étrangère Exemple: CASCADE • Suppression du tuple de la bière Bud de la relation Beers: – Alors supprimer tous les tuples de Sells qui ont beer = ’Bud’. • Mise à jour du tuple de la bière Bud en changeant ’Bud’ par ’Budweiser’: – Alors changer tous les tuples de Sells qui ont beer = ’Bud’ par beer = ’Budweiser’. Exemple: SET NULL • Suppression du tuple de la bière Bud de la relation Beers: – Alors changer tous les tuples de Sells qui ont beer = ’Bud’ par beer = NULL. • Mise à jour du tuple de la bière Bud en changeant ’Bud’ par ’Budweiser’: – même changement que pour la suppression. 129 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Choisir une politique de validation de contrainte Quand une clé étrangère est déclarée, la politique de validation de la contrainte peut être SET NULL ou CASCADE indépendamment des suppressions et des mises à jours. Faire suivre la déclaration de clé étrangère par: ON [UPDATE, DELETE][SET NULL, CASCADE] • Les deux clauses UPDATE ET DELETE peuvent être utilisées. • Si aucune n’est définie, celle par défaut est utilisée (rejet). 130 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Choisir une politique de validation de contrainte Exemple: définir une politique CREATE TABLE Sells ( bar CHAR(20), beer CHAR(20), price REAL, FOREIGN KEY(beer) REFERENCES Beers(name) ON DELETE SET NULL ON UPDATE CASCADE ); 131 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Contraintes sur les attributs Contraintes sur la valeur d’un attribut. Ajouter CHECK(<condition>) après la déclaration de l’attribut. La condition peut être définie sur l’attribut contraints, mais tout autre relations ou attributs doivent être dans une sous-requête. Exemple: CREATE TABLE Sells ( bar CHAR(20), beer CHAR(20) CHECK ( beer IN (SELECT name FROM Beers)), price REAL CHECK ( price <= 5.00 ) ); 132 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Timing des vérifications Vérifications des valeurs effectuées uniquement quand une valeur pour l’attribut contraint est insérée ou mise à jour. Exemple: • CHECK (price <= 5.00) - vérifie chaque nouveau prix et refuse la modification (pour le tuple visé) si le prix est supérieur à 5$. • CHECK (beer IN (SELECT name FROM Beers)) – vérifie que chaque nouvelle bière soit une bière référencée dans Beers – pas vérifié si une bière est supprimée de Beers, contrairement aux clés étrangères. 133 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Contraintes sur les tuples CHECK (<condition>) peut être ajoutée comme un élément de la définition du schéma de la relation. Dans ce cas, la condition peut traiter de tous les attributs de la relation. • mais l’utilisation d’un autre attribut ou d’une autre relation nécessite de faire une sous-requête Vérifiée à l’insertion ou lors de la mise à jour uniquement. Exemple: Seul les bars de Joe peuvent vendre de la bière à plus de 5$. CREATE TABLE Sells ( bar CHAR(20), beer CHAR(20), price REAL, CHECK (bar = ’Joe’’s Bar’ OR price <= 5.00) ); 134 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les Triggers: Motivation Les contraintes sur les attributs et les tuples sont vérifiées à des instants connus, mais ne sont pas “puissantes”. Les triggers laissent l’utilisateur décider à quel moment une condition doit être vérifiée. 135 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Des règles Evénement-Condition-Action Un autre nom des “trigger” est règles ECA, ou règles événementcondition-action. Evénement : typiquement un type de modification de la base de données, p.ex. “insertion dans Sells.” Condition : Toute expression booléenne SQL. Action : Toute instruction SQL. Exemple: A la place d’utiliser une clé étrangère et de rejeter les insertions dans Sells(bar, beer, price) avec des bières inconnues, un trigger peut ajouter cette bière à Beers, en mettant la valeur NULL pour le fabriquant. 136 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Définition d’un Trigger Exemple précédent: l’événement CREATE TRIGGER BeerTrig AFTER INSERT ON Sells REFERENCING NEW ROW AS NewTuple FOR EACH ROW WHEN (NewTuple.beer NOT IN (SELECT name FROM Beers)) INSERT INTO Beers(name) VALUES(NewTuple.beer); l’action la condition 137 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Options: CREATE TRIGGER CREATE TRIGGER BeerTrig AFTER INSERT ON Sells REFERENCING NEW ROW AS NewTuple FOR EACH ROW WHEN (NewTuple.beer NOT IN (SELECT name FROM Beers)) INSERT INTO Beers(name) VALUES(NewTuple.beer); CREATE TRIGGER <name> OU CREATE OR REPLACE TRIGGER <name> • utile pour remplacer ou modifier un trigger. 138 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Options: L’événement CREATE TRIGGER BeerTrig AFTER INSERT ON Sells REFERENCING NEW ROW AS NewTuple FOR EACH ROW WHEN (NewTuple.beer NOT IN (SELECT name FROM Beers)) INSERT INTO Beers(name) VALUES(NewTuple.beer); AFTER ou BEFORE • Egalement, INSTEAD OF, si la relation est une vue. INSERT, DELETE ou UPDATE • UPDATE peut être UPDATE OF <attribute list> ON … pour cibler un ou plusieurs attributs. Recommandations: • BEFORE pour vérifier ou modifier les données insérées ou maj • AFTER pour propager des modifications sur d'autres tables 139 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Options: FOR EACH ROW CREATE TRIGGER BeerTrig AFTER INSERT ON Sells REFERENCING NEW ROW AS NewTuple FOR EACH ROW WHEN (NewTuple.beer NOT IN (SELECT name FROM Beers)) INSERT INTO Beers(name) VALUES(NewTuple.beer); Les triggers sont “niveau ligne” ou “niveau instruction.” FOR EACH ROW indique un trigger niveau ligne; par défaut niveau instruction. Le triggers niveau ligne: executé une fois pour chaque tuple modifié. Les triggers niveau instruction: exécuté une fois pour chaque instruction SQL, peu importe le nombre de tuples modifiés. 140 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Options: REFERENCING CREATE TRIGGER BeerTrig AFTER INSERT ON Sells REFERENCING NEW ROW AS NewTuple FOR EACH ROW WHEN (NewTuple.beer NOT IN (SELECT name FROM Beers)) INSERT INTO Beers(name) VALUES(NewTuple.beer); Un événement INSERT implique un nouveau tuple (niveau ligne) ou une nouvelle table (niveau instruction) . • la “table” est l’ensemble des tuples insérés. DELETE implique un ancien tuple ou une table. UPDATE impliques les deux. En résumé [NEW OLD][ROW TABLE] AS <name> 141 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Options: La Condition CREATE TRIGGER BeerTrig AFTER INSERT ON Sells REFERENCING NEW ROW AS NewTuple FOR EACH ROW WHEN (NewTuple.beer NOT IN (SELECT name FROM Beers)) INSERT INTO Beers(name) VALUES(NewTuple.beer); Toute condition à résultat booléen. Evaluée sur la base de données avant ou après l’événement, en fonction de BEFORE ou AFTER. • mais toujours avant que les changements prennent effet. Accède au nouvel/ancien tuple/table grâce à la variable définie dans la clause REFERENCING. 142 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Options: L’Action CREATE TRIGGER BeerTrig AFTER INSERT ON Sells REFERENCING NEW ROW AS NewTuple FOR EACH ROW WHEN (NewTuple.beer NOT IN (SELECT name FROM Beers)) INSERT INTO Beers(name) VALUES(NewTuple.beer); Il peut y avoir plus d’une instruction SQL dans l’action. • Entouré par BEGIN . . . END s’il y en a plus d’une. Mais les requêtes d’interrogations n’ont pas de sens dans une action, une action est donc limitée à des requêtes de modifications. Attention: l'action peut déclencher à nouveau le trigger • Risque d'exécution infinie 143 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Un autre Exemple de trigger En utilisant Sells(bar, beer, price) et une relation unaire RipoffBars(bar), maintenir la liste des bars qui augmentent le prix d’une bière de plus de 1$. événement: uniquement les changements de prix CREATE TRIGGER PriceTrig AFTER UPDATE OF price ON Sells mises à jour -> accés aux REFERENCING anciens et nouveaux tuples OLD ROW AS ooo NEW ROW AS nnn considérer chaque changement de prix FOR EACH ROW WHEN(nnn.price > ooo.price + 1.00) condition: une INSERT INTO RipoffBars augmentation du prix > 1$ VALUES(nnn.bar); si le prix augmente assez, ajouter le bar dans RipoffBars 144 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Remarque sur la visibilité des modifications Quelles sont les données que voit un trigger lorsqu'il s'exécute ? • Dans certains cas pas évident car la requête Q qui a déclenché le trigger peut être encore active et faire des modifications Trigger niveau instruction • Si BEFORE évènement: aucune des modifications de Q visibles • Si AFTER évènement: toutes les modifications de Q visibles Trigger niveau ligne (FOR EACH ROW) • Si BEFORE événement: les modifications des lignes déjà traitées par Q sont visibles • pb: ordre de traitement des tuples pas prévisible • Si AFTER événement: toutes les modifications de Q visibles 145 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les Trigger dans PostgreSQL Les différences • Obligatoirement associé à une fonction qui retourne un objet trigger – Nécessité de créer la fonction d'abord, puis de créer le trigger – Déclaration d'une fonction sans arguments Possibilité de récupérer des arguments via le tableau TG_ARGV[] (la variable TG_NARGS donne le nombre d'arguments passés en paramètre) – Nécessité de retourner un objet trigger Si niveau instruction, RETURN NULL Si niveau ligne, si AFTER événement, RETURN NULL si BEFORE événement, RETURN NULL annule l'opération sur la ligne courante RETURN NEW pour valider INSERT/UPDATE RETURN OLD pour valider DELETE – Plusieurs variables prédéfinies permettant de récupérer des informations sur le trigger déclenché (nom, événement déclencheur, table visée, etc) TG_NAME, TG_WHEN, TG_LEVEL, TG_OP, TG_RELNAME,… 146 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les Trigger dans PostgreSQL Les différences (suite) • Référencer le tuple modifié (celui sur lequel se fait l'action) – NEW dans la fonction pour INSERT/UPDATE – OLD dans la fonction pour DELETE/UPDATE • Ne supporte pas les instructions REFERENCING … utilisation directe des variables NEW et OLD – p.ex. CREATE TRIGGER PriceTrig AFTER UPDATE OF price ON "Sells" REFERENCING OLD ROW AS ooo NEW ROW AS nnn … • Possibilité de préciser plusieurs évènements déclencheurs avec OR – CREATE TRIGGER BeerTrig AFTER INSERT OR BEFORE … ON "Sells" 147 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les exemples précédents dans PostgreSQL CREATE OR REPLACE FUNCTION trig_beer() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.beer NOT IN (SELECT name FROM Beers) ) THEN INSERT INTO "Beers"(name) VALUES (NEW.beer); END IF; RETURN NULL; END; $$ LANGUAGE 'plpgsql’; CREATE TRIGGER BeerTrigger AFTER INSERT ON "Sells" FOR EACH ROW EXECUTE PROCEDURE trig_beer() ; 148 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les exemples précédents dans PostgreSQL CREATE OR REPLACE FUNCTION trig_price() RETURNS TRIGGER AS ' BEGIN INSERT INTO "RipoffBars" VALUES (NEW.bar); RETURN NULL; END; ' LANGUAGE 'plpgsql' CREATE TRIGGER PriceTrig AFTER UPDATE ON "Sells" FOR EACH ROW WHEN ( NEW.price > OLD.price + 1.00 ) EXECUTE PROCEDURE trig_price(); 149 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les contraintes du point de vue théorique Différents concepts théoriques pour représenter les principaux types de contraintes (appelées aussi "classes de contraintes") • Dépendances fonctionnelles -> fondement théorique des clés et de la normalisation • Dépendances d'inclusions -> fondement théorique des clés étrangères • Dépendances multi-valuées, … Mécanismes formels pour exprimer des propriétés attendues pour les données Dépendances utilisées pour • protéger les données contre certaines anomalies (p.ex. avec des triggers) • améliorer la conception/maintenance d'un schéma • pour améliorer les performances 150 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Erreur de conception et Anomalies Bon schéma relationnel: • pas de redondance – redondance = plusieurs fois la même information • le fait que A.B. soit le fabricant de la Bud • pas d’anomalies. – Anomalie de mise à jour : une occurrence d’une information est modifiée et pas les autres • si Janeway part pour l’Intrepid, pensera-t-on à changer tous les nuplets? – Anomalie de suppression : une information pertinente est perdue en détruisant un n-uplet. : • si personne n’aime Bud, on perd le fait que son fabricant soit A.B. name Janeway Janeway Spock addr Voyager Voyager Enterprise beersLiked Bud WickedAle Bud manf A.B. Pete’s A.B. favBeer WickedAle WickedAle Bud 151 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Dépendances Fonctionnelles X -> A propriété d’une relation R si 2 n-uplets (tuples) sont égaux sur les attributs X alors ils sont égaux sur l’attribut A. • Quand c’est le cas, on dit que R satisfait la DF “X -> A ” Conventions: • …, X, Y, Z ensembles d’attributs; • On écrit ABC, plutôt que {A,B,C }. A, B, C,… attributs. Exemple: Drinkers(name, addr, beersLiked, manf, favBeer) FD naturelles pour ce schéma: 1. name -> addr 2. name -> favBeer 3. beersLiked -> manf 152 Les triggers Introduction aux contraintes en SQL Retour à la théorie: les dépendances Exemple name Janeway Janeway Spock addr Voyager Voyager Enterprise Parce que name -> addr beersLiked Bud WickedAle Bud manf A.B. Pete’s A.B. favBeer WickedAle WickedAle Bud Parce que name -> favBeer Parce que beersLiked -> manf 153 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances DF à plusieurs attributs Plus d’un attribut à droite: pratique mais pas indispensable • Pratique comme racourci pour plusieurs DF • Exemple: name -> addr name -> favBeer deviennent name -> addr favBeer Plus d’un attribut à gauche: essentiel. • Exemple: bar beer -> price 154 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Clés d’une Relation K est une clé de R ssi pour tout attribut A de R on a la DF K -> A K est une clé minimale de R ssi • K est une clé, • et aucun sous ensemble strict de K n’est une clé de R Exemple: Drinkers(name, addr, beersLiked, manf,favBeer) • {name, beersLiked} est une clé: ces 2 attributs déterminent tous les autres. name -> addr favBeer et beersLiked -> manf • {name, beersLiked} est une clé minimale: ni {name}, ni {beersLiked} ne sont des clés name ne détermine pas manf; beersLiked ne détermine pas addr. • – Il n’y a pas d’autre clé minimale, mais il y a beaucoup d’autres clés tout ensemble d’attributs contenant {name, beersLiked}. 155 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les dépendances d'inclusions (DI) Autre type de dépendances appelées dépendances d’inclusion (DI) ou ≪ contraintes d'intégrité référentielles ≫. Entre deux relations. Exemple: • Tout titre projeté actuellement (présent dans la relation Programme) est le titre d’un film (c’est-à-dire apparaissant dans la relation Films). Programme[Titre] ⊆ Films[Titre]. Les DI peuvent faire intervenir des séquences d’attributs de chaque côté. 156 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Différences DF versus DI Les DI se différencient des DF sur plusieurs points 1. Peuvent être définies entre attributs de relations différentes 2. Possèdent un caractère plus global (représentent les liens logiques entre des relations). 3. Les DI sont définies non pas entre deux ensembles quelconques d’attributs, mais entre deux séquences d’attributs de même taille. – L’ordre des attributs est donc très important pour les DI ! ! ! 157 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Syntaxe et sémantique des DI Soit R un schéma de base de données. Une dépendance d’inclusion sur R est une expression de la forme R [X ] ⊆ S [Y ], • où R,S ∈ R, X et Y sont des séquences d’attributs distincts respectivement de R et de S, et |X| = |Y|. Une DI est satisfaite dans une base de données si toutes les valeurs prises par la partie gauche apparaissent dans la partie droite. Autrement dit, • Soit d = {r1, r2, . . . , rn} une base de données sur un schéma R = {R1,...,Rn}. Une dépendance d’inclusion Ri[X] ⊆ Rj[Y] sur R est satisfaite dans d, noté d |= Ri[X] ⊆ Rj[Y], si ∀ti ∈ ri,∃tj ∈ rj tel que ti[X] = tj[Y] • de manière équivalente, πX (ri ) ⊆ πY (rj ). 158 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Exemple Supposons des schémas de relation pour décrire les modules : MODULE = {NUMMODULE ; INTITULE ; DESC } et un schéma de relation pour décrire les séances de cours : SEANCE = {DATE ; NUMMODULE ; NUMSALLE } Pour forcer que les numéros de modules dans les séances soient bien des modules qui existent, on devra alors définir la contrainte : SEANCE [NUMMODULE ] ⊆ MODULE [NUMMODULE ] 159 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances DI et clé étrangère Une contrainte d’intégrité référentielle est une DI dont la partie droite est une clé • Un attribut (ou ens. d’attributs) d’une relation apparaît comme clé d’une autre relation. La partie gauche d’une contrainte d’intégrité référentielle est appelée clé étrangère 160 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Exemple les DI ne définissent pas toujours des clés étrangères ! ! ! Il suffit d’imaginer qu’on souhaite imposer que tous les cours possèdent au moins une séance dans l’année. On définira alors une DI : COURS[NUMCOURS] ⊆ SEANCE[NUMCOURS] Tous les cours apparaîtront au moins une fois dans la relation des séances NUMCOURS n’est pas une clé de SEANCE (on imagine difficilement que tous les cours n’aient qu’une seule séance !) Donc ce n’est pas une clé étrangère 161 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les Dépendances : comment les trouver et pourquoi ? Comment les trouver ? • L'analyse du problèmes donne des dépendances de bon sens – • “jamais deux cours à la même heure dans la même salle” heure salle -> cours. Problème: – des dépendances peuvent être impliquées de façon implicite par d'autres dépendances nom -> adresse et adresse -> ville, donc nom -> ville – ces contraintes implicites peuvent échapper à la connaissance du concepteur Nécessité de méthodes permettant de déduire l'ensemble des dépendances induites par un ensemble de dépendances de départ • Inférence des DF, DI, … 162 Introduction aux contraintes en SQL Les triggers Retour à la théorie: les dépendances Les Dépendances : comment les trouver et pourquoi ? Pourquoi cette formalisation théorique des contraintes ? • Exhiber des propriétés théoriques • Définir des algorithmes permettant de découvrir automatiquement les dépendances – • même celles implicites Normaliser les schémas pour éviter les anomalies dans les données – normaliser = décomposer les schémas en fonction des dépendances 163 Chapitre 2: Définir et structurer les bases de données Définir des vues des données (dérivé du cours du Pr. Jeffrey Ullman, Stanford University) Université de la Nouvelle-Calédonie [email protected] Les Vues Une vue est une relation définie en fonction de tables stockées (appelée tables de base) et d’autres vues. Il existe deux types de vues: 1. Virtuelles = pas stockées dans la base de données; juste une requête enregistrée construisant à chaque appel la relation. 2. Matérialisées = relation réellement construite et enregistrée. 165 Déclarer une Vue Déclaré par l’instruction SQL: CREATE [MATERIALIZED] VIEW <name> AS <query>; • Par défaut, la vue est virtuelle. Exemple: • CanDrink(drinker, beer) est une vue « contenant » les pairs buveur-bière tel que le buveur fréquente au moins un bar proposant la bière: CREATE VIEW CanDrink AS SELECT drinker, beer FROM Frequents, Sells WHERE Frequents.bar = Sells.bar; 166 Accéder à une Vue Interroger une vue comme si c’était une table de base. Dans certains cas, possibilité de modifier le contenu d’une vue si celle-ci ne dépend que d’une seule table de base. • modifier = INSERT, DELETE, UPDATE • par contre ALTER toujours possible Exemple: SELECT beer FROM CanDrink WHERE drinker = ’Sally’; 167 Modification de Vues grâce à des Triggers En général, il est impossible de modifier directement une vue virtuelle, tout simplement parce qu’elle n’existe pas concrètement. • Dans PostgreSQL, modification automatique des données sous-jacentes (table complète ou certaines colonnes) possible ssi – une seule table dans le FROM, – pas de DISTINCT, GROUP BY, LIMIT, UNION, INTERSECT, EXCEPT, etc – aucun opérateur d'agrégation et aucune fonction retournant des ensembles dans le SELECT Mais l’option d’événement INSTEAD OF des triggers permet d’interpréter des modifications sur des vues d’une manière qui fait sens. CREATE TRIGGER <nom> INSTEAD OF [INSERT, DELETE, UPDATE] ON <nomVue> [FOR EACH ROW] WHEN <condition> <fonction trigger PL/pgSQL> 168 Modification de Vues grâce à des Triggers Exemple: • La vue Synergy est composée du triplet (drinker, beer, bar) et représente les buveurs, les bières qu’ils aiment, ainsi que les bars qui les servent. Prend une copie de chaque attribut CREATE VIEW Synergy AS SELECT Likes.drinker, Likes.beer, Sells.bar FROM Likes, Sells, Frequents WHERE Likes.drinker = Frequents.drinker AND Likes.beer = Sells.beer AND Sells.bar = Frequents.bar; Jointure naturelle entre Likes, Sells, et Frequents 169 Modification de Vues grâce à des Triggers Exemple (suite): • Nous ne pouvons pas insérer dans Synergy --- c’est une vue virtuelle. • Mais nous pouvons utiliser à la place un trigger avec INSTEAD OF pour transformer l’insertion d’un tuple (drinker, beer, bar) en trois insertions sur Likes, Sells, et Frequents. – Sells.price aura la valeur NULL. CREATE TRIGGER SynergyViewTrig INSTEAD OF INSERT ON Synergy FOR EACH ROW EXECUTE PROCEDURE insertSynergyView(); CREATE FUNCTION insertSynergyView() RETURNS TRIGGER AS $$ BEGIN INSERT INTO LIKES VALUES(new.drinker, new.beer); INSERT INTO SELLS(bar, beer) VALUES(new.bar, new.beer); INSERT INTO FREQUENTS VALUES(new.drinker, new.bar); END; $$ LANGUAGE plpgsql; 170 Les vues Matérialisées CREATE MATERIALIZED VIEW <name> [ (<colomn_name [,…]) ] AS <query>; Problème: chaque fois qu’une table de base change, la vue matérialisée peut changer. • Il faut reconstruire la vue à chaque changement. Solution: Reconstruction périodique de la vue matérialisée, qui sans cela serait "périmée". L’implémentation dépend du SGBD. • Dans PostgreSQL, – uniquement disponible depuis la version 9.3 – utiliser la commande REFRESH MATERIALIZED VIEW <name> pour rafraîchir les données de la vue 171 Les vues Matérialisées Exemples: • Mailing List d’une classe – La mailing list d’une classe peut être obtenue par une vue matérialisée sur la table de base contenant tous les étudiants. – si la vue est mise à jour 4 fois par jours, les étudiants enregistrés entre deux mises à jour ne recevront pas les mails. • Un entrepôt de données – Les magasins Wal-Mart stockent les ventes de tous les magasins dans une base de données. – Pendant la nuit, les ventes du jour sont utilisées pour mettre à jour un entrepôt de données (data warehouse) = des vues matérialisées sur les ventes. – L’entrepôt est utilisé par les preneurs de décision pour prédire les tendances et envoyer des produits là où ils se vendent le mieux. 172 Chapitre 2: Définir et structurer les bases de données Inférence des DF et normalisation (dérivé du cours du Pr. Jeffrey Ullman, Stanford University et du cours du Pr. Christian Retoré, Université de Bordeaux) Université de la Nouvelle-Calédonie [email protected] PLAN Inférence des DF Normalisation de bases de données 174 Rappels sur les Dépendances Fonctionnelles La DF X -> Y est satisfaite dans la relation R ssi 2 tuples égaux sur les attributs X sont aussi égaux sur les attributs Y • p.ex. name -> addr favBeer • Une clé primaire représente un cas particulier de DF Intérêt des DF: améliorer le schéma des bases de données en évitant des anomalies • Anomalie de mise à jour et anomalie de suppression Des DF peuvent être déduites en analysant le problème (p.ex. heure salle -> cours) Problème: des DF implicites pouvent échappées à cette analyse • Problème de l'inférence des DF, i.e. à partir d'un ensemble de DF connues, comment trouver toutes les DF satisfaites par une relation 175 Déduire des DF On se donne F un ensemble de DF: X1 -> A1, X2 -> A2,…, Xn -> An , et on souhaite savoir si une DF Y -> B est la conséquence sémantique de F • c’est-à-dire Y -> B est satisfaite dans tout modèle satifaisant F. Exemple: • Si A -> B et B -> C sont vraies, sans doute que A -> C aussi, même si on ne le dit pas. Important pour la conception de bons schémas relationnels. 176 Test d'inférence Pour tester si Y -> B, commencer par supposer que deux tuples sont égaux sur tous les attributs de Y Y 0000000. . . 0 00000?? . . . ? Utiliser l'ensemble de DF de départ pour en déduire que les tuples sont égaux sur d’autres attributs • Si B est l’un des attributs pour lesquels il y a égalité alors Y -> B est vrai • Sinon les 2 tuples, avec les égalités induites par les dépendances, forment un contre-exemple demontrant que Y -> B n'est pas une conséquence des DF de départ 177 Test d'inférence Exemple : • DF données { C->B , AB->D } • AC-> D ? A B C D E A B C D E A B C D E a’ b’ c’ d’ e’ a’ b’ c’ d’ e’ a’ b’ c’ d’ e’ a’ a’ b’ c’ a’ b’ c’ d’ c’ C->B Donc AC->D est satisfait AB->D • AB-> C ? 178 Test de fermeture Une façon plus simple pour inférer des DF est de calculer la fermeture de Y, noté Y+ • Etant donné un ensemble F de DF et X est un ensemble d’attributs, on note X+ l’ensemble des attributs A tels que X->A est conséquence de F Fermeture d'un ensemble d'attributs Initialisation: Y + = Y. Induction: Rechercher une partie gauche de DF dans F qui soit inclue dans le Y + courant. Si la DF est X->A, ajouter A à Y +. Répéter ces opérations jusqu'à ce que l'on n'ajoute plus de nouveaux attributs dans Y+. • Autrement dit, Y+n+1=Y+n U {A| Z->A et Z inclus dans Y+n} • Arrêt: stabilité Y+n+1=Y+n X Y+ A new Y+ 179 Test de fermeture Exemple : • Soit F = { AB->C, C->A, BC->D, ACD->B, D->EG, BE->C, CG->BD, CE->AG }, quelle est la fermeture de BD ? • Initialisation: BD+={B,D} • Itération 1: – rechercher les DF dont la partie gauche est dans BD+: D->EG – ajouter leur partie droite dans la fermeture: BD+={B,D,E,G} • Itération 2: – rechercher les DF dont la partie gauche est dans le nouveau BD+: D->EG, BE->C – ajouter leur partie droite dans la fermeture: BD+={B,D,E,G,C} • Itération 3: – rechercher les DF dont la partie gauche est dans le nouveau BD+: C->A, BC->D, D->EG, BE->C, CE->AG – ajouter leur partie droite dans la fermeture: BD+={B,D,E,G,C,A} • … 180 Idée simple pour trouver toutes les DF Commencer à partir d'un ensemble de DF connues et trouver toutes les DF non triviales qui découle de cet ensemble de DF • non triviale = partie droite non inclue dans la partie gauche Fermeture d'un ensemble de DF Un algorithme simple, mais exponentiel 1. 2. 3. Pour chaque ensemble d’attribut X de la relation, on calcule X +. Ajouter X ->A pour tout A dans X + - X. Supprimer XY ->A si on découvre X ->A. car XY ->A découle de X ->A quelle que soit la manière dont on projette Astuces: • • Inutile de calculer la fermeture de l'ensemble contenant tous les attributs et celle de l'ensemble vide Si on trouve X + = tous les attributs, alors il en va de même de tout X’ contenant X 181 Idée simple pour trouver toutes les DF Exemple: • Soit la relation ayant pour schéma {A,B,C} avec les DF A ->B et B ->C, cad F={A->B, B->C} • • • • • • A +=ABC ; donne A ->B, A ->C B +=BC ; donne B ->C C +=C ; ne donne rien AB + ; inutile de calculer car A += tous les attributs AC + ; inutile de calculer car A += tous les attributs BC +=BC ; ne donne rien • DF obtenues: F+={A ->B, A ->C, B ->C} 182 Objectif de l'inférence des DF Motivation: "normalisation", le processus où le schéma d'une relation est divisé en plusieurs schémas. Exemple: Soit une relation R ayant pour schéma {A,B,C,D} avec l'ensemble de DF {AB->C, C->D, D->A} • Décomposer en 2 schémas {A,B,C} et {A,D}. • Quelles DF doivent être satisfaites dans {A,B,C} ? non seulement AB->C mais aussi C->A ! ABCD a1 b 1 c d 1 a2 b 2 c d 2 d1=d2 parce que C -> D a1 b 1 c a2 b 2 c a1=a2 parce que D -> A donne ABC Ainsi, des tuples issus de la projection avec les mêmes valeurs pour C ont la même valeur pour A, cad C -> A. 183 PLAN Inférence des DF Normalisation de bases de données 184 Design de schéma relationnel L'objectif du design de schéma relationnel est d'éviter les anomalies et les redondances • Anomalie de mise à jour : une occurrence d’une information est modifiée et pas les autres • Anomalie de suppression : une information pertinente est perdue en détruisant un n-uplet. Exemple de mauvais design: Drinkers(name, addr, beersLiked, manf, favBeer) name Janeway Janeway Spock addr Voyager ??? Enterprise beersLiked Bud WickedAle ??? manf A.B. Pete’s A.B. favBeer WickedAle ??? Bud Les données sont redondantes, car chaque ??? peut être retrouvé en utilisant les DF name -> addr favBeer et beersLiked -> manf. 185 Design de schéma relationnel Ce mauvais schéma fait aussi ressortir des anomalies name Janeway Janeway Spock addr Voyager Voyager Enterprise beersLiked Bud WickedAle Bud manf A.B. Pete’s A.B. favBeer WickedAle WickedAle Bud • Anomalie de mise à jour: si Janeway part pour l’Intrepid, pensera-t-on à changer tous les tuples? • Anomalie de suppression: si personne n’aime Bud, on perd le fait que son fabricant soit Anheuser-Busch. Besoin de propriétés, de règles, de méthodes permettant de concevoir de bons schémas 186 Forme Normale de Boyce-Codd (BCNF) Une relation R est dite en BCNF ssi pour toute Dépendance Fonctionnelle non triviale X ->A sur les attributs de R, X est une super clé. • non triviale = X ne contient pas A • super clé = clé (minimale) ou sur-ensemble d'une clé (minimale) Exemple: Drinkers(name, addr, beersLiked, manf, favBeer) DF: name->addr favBeer, beersLiked->manf • Une seule clé minimale {name, beersLiked}. • Pour chaque DF: la partie gauche n’est pas une super clé • Drinkers n’est pas en BCNF (prendre l’une des deux DF au choix) 187 Forme Normale de Boyce-Codd (BCNF) Autre exemple: Beers(name, manf, manfAddr) DF: name->manf, manf->manfAddr • Une seule clé minimale {name} . • name->manf ne contredit pas BCNF, mais par contre la relation n’est pas BCNF à cause de manf->manfAddr . 188 Décomposer un schéma en BCNF Soit une relation R avec un ensemble F de DF Chercher les DF X ->B telles que X ne soit pas une clé • Si R pas BCNF, il y en a au moins une. Calculer X +. • Rq: X + ne contient pas tous les attributs, sinon X serait une clé. Décomposer R en suivant X->B • Remplacer R par par deux relations dont les attributs sont: R1=X+ – R1 = X + – R2 = R – (X + – X ) • Projeter les DF de la fermeture de F sur ces deux nouveaux schémas R-X+ X +- X X R2 R 189 Décomposer un schéma en BCNF Exemple : Drinkers(name, addr, beersLiked, manf, favBeer) F = { name->addr, name -> favBeer, beersLiked->manf } • Trouver une DF qui fait que Drinkers n’est pas en BCNF: name->addr • Calcule de la fermeture des attributs de la partie gauche: {name}+ = {name, addr, favBeer} • On obtient deux relations: 1. Drinkers1(name, addr, favBeer) = {name}+ 2. Drinkers2(name, beersLiked, manf) = {name, addr, beersLiked, manf, favBeer} - {addr, favBeer} 190 Décomposer un schéma en BCNF Exemple (suite) : • Ce n'est pas fini; nous devons vérifier que Drinker1 et Drinker2 sont en BCNF • Projeter les DF est assez facile pour ce cas (car F=F+) – F+ = { name->addr, name -> favBeer, beersLiked->manf } – Pour Drinkers1(name, addr, favBeer), les DF pertinentes sont name->addr et name->favBeer. – {name} est donc la seule clé et Drinkers1 est en BCNF. – Pour Drinkers2(name, beersLiked, manf), la seule DF est beersLiked->manf, et la seule clé est {name, beersLiked}. Pas BCNF, on recommence la décomposition pour Drinkers2. 191 Décomposer un schéma en BCNF Exemple (suite) : • La DF qui fait que Drinkers2 n’est pas en BCNF est beersLiked->manf • Calcule de la fermeture {beersLiked}+ = {beersLiked, manf} • On décompose donc Drinkers2 en 1. Drinkers3(beersLiked, manf)=X+ 2. Drinkers4(name, beersLiked)={name,beersLiked,manf} - {manf} • Projeter les DF de l'ensemble F+ dans ces nouveaux schémas – Pour Drinkers3(beersLiked, manf), la seule DF pertinente est beersLiked->manf – {beersLiked} est donc la seule clé et Drinkers3 est en BCNF – Pour Drinkers4(name, beersLiked), aucune DF (implicite ou pas) n'est pertinente – {name, beersLiked} est clé et Drinkers4 est en BCNF 192 Décomposer un schéma en BCNF Exemple (fin) : Décomposition de Drinkers : 1. Drinkers1(name, addr, favBeer) 2. Drinkers3(beersLiked, manf) 3. Drinkers4(name, beersLiked) • Rq: Drinkers1 décrit les personnes, Drinkers3 décrit les bières, et Drinkers4 décrit la relation entre les personnes et les bières. Drinkers1 name addr favBeer Janeway Voyager WickedAle Spock Enterprise Bud Drinkers3 beersLiked manf Bud A.B. WickedAle Pete's Drinkers4 name beersLiked JaneWay Bud JaneWay WickedAle Spock Bud 193 Problème de la décomposition en BCNF Certaines configurations de DF posent problème lorsque l'on essaye de décomposer un schéma en BCNF Exemple: • AB ->C et C ->B avec A = street, B = city, et C = zip • Il y a deux clés, {A,B } et {A,C } • C ->B contredit BCNF, il faudrait décomposer en {A,C} et {B,C} • Problème: si nous utilisons ces schémas, nous ne retrouvons plus la DF AB ->C à partir des DF projetées 194 Exemple de DF non préservée street zip 545 Tech Sq. 02138 545 Tech Sq. 02139 city Cambridge Cambridge zip 02138 02139 faire une jointure sur le code postal street city 545 Tech Sq. Cambridge 545 Tech Sq. Cambridge zip 02138 02139 Bien qu'aucune DF ne soit violée dans chacune des relations décomposées, la DF street city -> zip est violée dans la base de données dans son ensemble 195 La 3NF évite le problème de non préservation des DF 3e Forme Normale (3NF) assouplit la condition de BCNF pour garantir une décomposition préservant les DF Un attribut est dit premier s’il fait partie d’une clé minimale. Une relation n’est pas en 3NF ssi on peut trouver une DF X ->A telle que • X n’est pas une clé et • A n'est pas premier (ne fait pas partie d’une clé minimale) Exemple : • Dans l'exemple précédent avec la relation ayant pour schéma {A,B,C} et les DF {AB ->C, C ->B} • Les clés minimales sont AB et AC • Chaque attribut A, B, ou C est premier • Bien que C ->B contredise BCNF, ce schéma est en 3NF 196 Couverture minimale des DF Besoin de calculer une couverture minimale des DF pour décomposer en 3NF • Toutes DF a un seul attribut à droite • Aucune DF ne peut être retirée – si on en retire une, la fermeture de la couverture minimale n'est plus égale à celle de l'ensemble de DF de départ • Aucun attribut ne peut être enlevé – sans changer le résultat de la fermeture Plus petit ensemble de DF équivalent leurs fermetures sont égales Méthode: 1. Décomposer chaque DF pour avoir un seul attribut à droite 2. Supprimer les attributs en surnombre à gauche 3. Supprimer les DF redondantes 197 Exemple de couverture minimale des DF Soit F={A->B, ABCD->E, EF->G, EF->H, ACDF->EG} Décomposition des DF pour avoir un seul attribut à droite • ACDF->EG devient ACDF->E et ACDF->G F={A->B, ABCD->E, EF->G, EF->H, ACDF->E,ACDF->G} Suppression des attributs en surnombre à gauche (tester chaque attribut de chaque DF) • ABCD->E peut être remplacé par ACD->E car ABCD+=ACD+ (grâce à A->B) F={A->B, ACD->E, EF->G, EF->H, ACDF->E,ACDF->G} Suppression les DF redondantes • ACDF->G peut être supprimé car cette dépendance est impliquée par ACD->E et EF->G • idem pour ACDF->E F={A->B, ACD->E, EF->G, EF->H} 198 Construction d'une décomposition 3NF Soit une relation R et un ensemble F de DF Calculer une couverture minimale de F Pour chaque DF X->A dans cette couverture minimale, créer une relation ayant pour schéma {X,A} Si la clé (minimale) n'est pas contenue dans aucune DF, alors ajouter une relation avec pour schéma la clé Exemple : • Soit la relation R avec pour schéma {A,B,C}, pour ensemble de DF F={A->B, C->B}, et pour clé minimale {A,C} • La couverture minimale est {A->B, C->B} • Création de deux relations à partir des DF: R1={A,B} et R2={C,B} • Création d'une relation à partir de la clé de R: R3={A,C} 199 Propriétés importantes pour les décompositions Préservation des dépendances fonctionnelles • On peut vérifier dans les relations projetées que les dépendances originales sont préservées. • Contre-exemple: décomposition BCNF de street-city-zip où street city -> zip n'est plus forcément vérifié Décomposition Sans Perte d’Information (SPI) • On peut projeter la relation de départ sur chacune des composantes et reconstruire la relation de départ. • • une décomposition BCNF vérifie SPI Exemple: décomposition de Drinkers en Drinkers1, Drinkers3 et Drinkers4 200 Comment tester une décomposition préservant les DF ? Soit un ensemble F de DF connues et une décomposition de la relation R en R1, R2, … Rk Calculer la fermeture F+ de l'ensemble des DF Projeter cet ensemble de DF sur les relations issues de la décomposition • Pour chaque relation Ri, conserver uniquement les DF composées des attributs de Ri • On obtient donc k ensembles de DF: FR1, FR2,… FRk • Rappel: méthode utilisée pour la décomposition en BCNF Faire l'union des DF projetées sur R1, R2, … Rk et vérifier que le résultat est bien égale à F+ • Autrement dit, (FR1 U FR2 U… U FRk)+=F+ 201 Comment tester une décomposition SPI ? Soit une décomposition de la relation R en R1, R2, … Rk Si on projette les données de R dans R1, R2, … Rk, peut-on retrouver R en faisant une jointure ? • Tout tuple de R peut être retrouvé à partir de ses fragments projetés • Donc la seule question est: quand nous faisons la jointure, a-t-on des tuples supplémentaires qui n'existaient pas initialement ? πName,Branch(r) Name Project Branch Brown Mars L.A. Green Venus Miami Hoskins Saturn Miami Brown L.A Green Miami Hoskins Miami πProject,Branch(r) Project Branch πName,Branch(r) πProject,Branch(r) Name Jointure Name Décomposition r Branch Project Branch Brown Mars L.A. Green Venus Miami Hoskins Saturn Miami Mars L.A. Green Saturn Miami Venus Miami Hoskins Venus Miami Saturn Miami 202 Le test de Chase Supposons qu'un tuple t = abc… soit construit par la jointure des relations Ri issues de la décomposition Créer un tableau représentant le résultat de la jointure des relations décomposées Pour chaque relation décomposée Ri, créer un tuple dans ce tableau tel qu'il a les valeurs • a,b,c… pour les attributs de Ri • ai,bi,ci… pour les autres attributs • Exemple: – soit R={A,B,C,D} décomposé en trois relations R1={A,B}, R2={B,C} et R3={C,D} A B C D a b c1 d1 a2 b c d2 a3 b3 c d 203 Le test de Chase (suite) Appliquer l'ensemble des DF connues afin de déduire des égalités dans les données • Si deux tuples ont les mêmes valeurs pour une partie gauche de DF, faites que leurs valeurs pour les attributs de la partie droite correspondent aussi • Remplacer par les valeurs du tuples t=abc… • Exemple (suite) A – F={C->D, B->A} donc car B->A B C D a b c1 d1 a a2 b c d d2 a3 b3 c d car C->D Si une ligne correspondant au tuple t=abc… apparaît, décomposition SPI Sinon, perte d'informations • Exemple (fin): décomposition SPI 204 Exemple de décomposition avec perte d'informations Soit R={A,B,C,D} décomposé en trois relations R1={A,B}, R2={B,C} et R3={C,D F={C->D} A Construction du tableau Application des DF • C->D B C D a b c1 d1 a2 b c d2 a3 b3 c d A B C D a b c1 d1 a2 b c d a3 b3 c d Décomposition avec perte d'informations car on ne retrouve pas le tuple abc 205 Propriétés des décompositions 3NF et BCNF Décomposition Sans Perte d’Information Préservation des dépendances fonctionnelles BCNF 3NF oui oui Pas forcément (ex: street-city-zip) oui 206