Vous êtes sur la page 1sur 31
Module 215 Bases de Données Avancées SGBD Objet-Relationnel 1 - Généralités 2 - SQL3 3

Module 215

Bases de Données Avancées

SGBD Objet-Relationnel

1 - Généralités 2 - SQL3 3 - Oracle

Bibliographie

Gérard-Michel Cochard

Généralités

1. Introduction

Contenu :

2. Types abstraits de données

3. Les objets

4. Modélisation des associations

1. Introduction

Il y a deux limites principales au modèle relationnel :

l'approche orientée objet n'est pas prévue : les concepts d'objet, d'héritage, d'encapsulation,

Le modèle relationnel ne manipule que des données classiques. Il n'existe pas de structures de données complexes comme des données multimédias ou des tables par exemple.

lui sont étrangers.

A partir de ce constat, on peut envisager deux types de solutions :

1ère possibilité : abandonner le modèle relationnel et construire un nouveau modèle "objet" de bases de données qui devraient obéir aux 13 règles énoncées précédemment. De tels modèles existent mais leur commercialisation sous forme de SGBD est lente et ils ne sont vraiment utilisés que dans des créneaux très spécialisés. Il faut dire que les éditeurs de SGBD relationnels ne sont enclins à passer brutalement à des modèles objets pour des raisons économiques très compréhensibles.

2ème possibilité : étendre le modèle relationnel vers un modèle objet-relationnel (il serait plus exact de dire "relationnel-objet"). Il s'agit de rendre le modèle relationnel compatible avec les "règles" objet. De fait, il y a trois extensions essentielles par rapport au modèle relationnel standard :

l'incorporation de structures de données complexes : les types abstraits de données (TAD en français, ADT en anglais).

l'introduction des objets, notamment via leur identifiant (appelé oid : object identifier)

la modélisation des associations

Les SGBD commerciaux, basés sur le modèle Objet-relationnel sont en général issus du modèle Relationnel. Citons, parmi les plus connus :

Oracle 8i, 9i

Sybase

DB2

UNISQL

UNISYS

du modèle Relationnel. Citons, parmi les plus connus : ● Oracle 8i, 9i ● Sybase ●
du modèle Relationnel. Citons, parmi les plus connus : ● Oracle 8i, 9i ● Sybase ●
du modèle Relationnel. Citons, parmi les plus connus : ● Oracle 8i, 9i ● Sybase ●
du modèle Relationnel. Citons, parmi les plus connus : ● Oracle 8i, 9i ● Sybase ●

2 - Les types abstraits de données

Dans le modèle relationnel, les types de données sont prédéfinis (nombre, caractères, date,

types abstraits de données (TAD) sont des types d'attributs définis par l'utilisateur, incluant des attributs mais aussi des méthodes (fonctions, procédures). Les TAD peuvent aussi être définis à partir d'autres TAD.

).

Dans le modèle objet-relationnel, les

Dans ce qui suit, on utilisera une syntaxe de type SQL pour la description, la manipulation et l'interrogation de données.

exemple :

création du type Tadresse :

CREATE TYPE Tadresse ( num NUMBER, voie CHAR(30), ville(30), cp (CHAR(10));

création du type Tpersonne :

CREATE TYPE Tpersonne (nom CHAR(30), pnom CHAR(30), adr Tadresse);

création d'une table ANNUAIRE :

CREATE TABLE ANNUAIRE OF Tpersonne

table ANNUAIRE : CREATE TABLE ANNUAIRE OF Tpersonne Sur cet exemple, on voit que l'on a

Sur cet exemple, on voit que l'on a incorporé dans une table un objet complexe adr.

On peut incorporer ainsi des objets nouveaux comme des images que l'on peut insérer sous forme de BLOB qui est un type prédéfini pour des objets de grande dimension.

exemple : création d'une table avec des images stockées dans la base de données

CREATE TABLE TROMBINOSCOPE (personne Tpersonne, photo BLOB);

table avec des images stockées dans la base de données CREATE TABLE TROMBINOSCOPE (personne Tpersonne, photo

Un autre nouveau type est le pointeur qui comme son nom l'indique, désigne l'adresse d'un tuple.

exemple :

CREATE TYPE Tadresse (num NUMBER, voie CHAR(30), ville CHAR(30), cp CHAR(10); CREATE TYPE Tpersonne(nom CHAR(30), pnom CHAR(30), adr REF Tadresse); CREATE TABLE ADRESSE OF Tadresse; CREATE TABLE PERSONNE OF Tpersonne;

CHAR(30), pnom CHAR(30), adr REF Tadresse); CREATE TABLE ADRESSE OF Tadresse; CREATE TABLE PERSONNE OF Tpersonne;

On peut aussi définir des ensembles de données que l'on appelle collection. Un tuple peut donc ainsi contenir des attributs non atomiques en violation avec la première forme normale du modèle relationnel. On dit que cette possibilité est NF2 (Non-First Normal Form).

exemple :

CREATE TYPE Ttelephone (tel CHAR(20)); CREATE TYPE Tpersonne(nom CHAR(40), pnom CHAR(20), listel SET(Ttelephone)); CREATE TABLE PERSONNE OF Tpersonne;

CHAR(20)); CREATE TYPE Tpersonne(nom CHAR(40), pnom CHAR(20), listel SET(Ttelephone)); CREATE TABLE PERSONNE OF Tpersonne;

3 - L'objet

En reprenant l'exemple précédent, on peut imaginer qu'une collection ne comporte pas un nombre fixé d'éléments et on peut aussi bien en ajouter qu'en supprimer.

exemple : dans le TAD précédent, on peut définir les méthodes ajouter_tel() et supprimer_tel() :

CREATE TYPE Tpersonne( nom CHAR(30), pnom CHAR530), listel SET(Ttelephone), METHOD ajouter_tel(nouveau_tel Ttelephone), METHOD supprimer_tel(tel Ttelephone));

Cet exemple monter que l'encapsulation des objets est bien mise en oeuvre. Il en est de même que l'héritage :

exemple : supposons que l'on ait défini le type Tpersonne et que l'on ait deux autres types, Tclient et Tfournisseur, chacun de ces deux types héritant des attributs et des méthodes de Tpersonne.

types héritant des attributs et des méthodes de Tpersonne. On définira les deux types Tclient et

On définira les deux types Tclient et Tfournisseur comme suit :

CREATE TYPE Tclient UNDER Tpersonne(numclient NUMBER); CREATE TYPE Tfournisseur UNDER Tpersonne(numfour NUMBER, article CHAR(80));

Les nouveaux types héritent des attributs et méthodes de Tpersonne mais possèdent des attributs spécifiques supplémentaires.

types héritent des attributs et méthodes de Tpersonne mais possèdent des attributs spécifiques supplémentaires.

Un objet de la base est représenté par son identifiant oid. L'utilisateur n'a pas à s'en soucier. En revanche c'est le SGBD qui l'utilise, de manière transparente, pour rechercher et trouver les objets via leur oid. Pour montrer la différence avec le modèle relationnel examinons quelques exemples de requêtes.

exemple : une cuisine pour collectivités est organisée en équipes de cuisiniers ; chaque équipe est dirigée par un chef d'équipe.

Dans le modèle relationnel, on peut représenter la situation par une table

CUISINIER ( numero, nom, prenom, chef)

par une table CUISINIER ( numero, nom, prenom, chef) Considérons les deux requêtes suivantes : R

Considérons les deux requêtes suivantes :

R1 : Quel est le chef du cuisinier 26 ?

La solution, avec SQL2, peut être :

SELECT numero, nom, prenom FROM CUISINIER WHERE numero = (SELECT chef FROM CUISINIER WHERE

numero=26);

R2 : Quels sont les cuisiniers de l'équipe dirigée par Alain DUBOIS ?

SELECT numero, nom, prenom FROM CUISINIER WHERE chef = (SELECT numero FROM CUISINIER WHERE nom='DUBOIS' AND prenom = 'Alain');

Dans le modèle objet-relationnel, une occurrence de CUISINIER peut être considérée comme un objet (qui sera repéré par son oid). Il y a toutefois plusieurs manières de représenter la table CUISINIER.

1ère représentation : utilisation de pointeurs

CUISINIER. 1ère représentation : utilisation de pointeurs 2ème représentation : utilisation de tableaux de pointeurs

2ème représentation : utilisation de tableaux de pointeurs

Passons aux requêtes ci-dessus : SELECT c.chef.numero, c.chef.nom, c.chef.prenom FROM CUISINIER c WHERE c.numero=26;

Passons aux requêtes ci-dessus :

SELECT c.chef.numero, c.chef.nom, c.chef.prenom FROM CUISINIER c WHERE c.numero=26;

SELECT c.numero, c.nom, c.prenom FROM CUISINIER c WHERE c.chef.nom = "DUBOIS' AND c.chef.prenom = 'Alain';

On notera l'écriture qui fait usage d'un alias. Un objet pointé s'écrit ainsi alias.pointeur.objet_pointé.

exemple : Considérons maintenant des requêtes sur deux tables. En reprenant l'exemple précédent, considérons que dans le modèle relationnel, la situation est décrite par deux tables EQUIPE et CUISINIER

EQUIPE(numeq, nomeq) CUISINIER(numero, nom, prenom, numeq)

EQUIPE(numeq, nomeq) CUISINIER(numero, nom, prenom, numeq) Exprimons les requêtes suivantes en SQL2 : R1 : Quels

Exprimons les requêtes suivantes en SQL2 :

R1 : Quels sont le numéro et le nom de l'équipe des cuisiniers de prénom "Jean" ?

SELECT numero, nom FROM EQUIPE WHERE numeq IN (SELECT numeq FROM CUISINIER WHERE prenom = 'Jean');

ou bien

SELECT numero, nom FROM EQUIPE, CUISINIER WHERE prenom = 'Jean' AND EQUIPE.numeq = CUISINIER.numeq ;

R2 : Quels sont les numéros, les noms et les prénoms des cuisiniers de l'équipe "miammiam" ?

SELECT numero, nom, prenom FROM CUISINIER WHERE numeq IN (SELECT numeq FROM EQUIPE WHERE nomeq = 'miammiam');

ou bien

SELECT numero, nom, prenom FROM CUISINIER, EQUIPE WHERE nomeq = 'miammiam' AND CUISINIER.numeq = EQUIPE.numeq;

Dans le modèle objet-relationnel, on peut envisager 4 solutions

pointeurs fils --> père

peut envisager 4 solutions ● pointeurs fils --> père SELECT c.equ.numeq, c.equ.nomeq FROM CUISINIER c WHERE

SELECT c.equ.numeq, c.equ.nomeq FROM CUISINIER c WHERE c.prenom = 'Jean';

pointeurs père --> fils

SELECT c.numero, c.nom, c.prenom FROM CUISINIER c WHERE c.equ.nomeq = 'miammiam';

FROM CUISINIER c WHERE c.equ.nomeq = 'miammiam'; SELECT e1.numeq, e1.nomeq FROM EQUIPE e1 WHERE EXISTS

SELECT e1.numeq, e1.nomeq FROM EQUIPE e1 WHERE EXISTS (SELECT REF(c) FROM CUISINIER c WHERE c.prenom = 'Jean') INTERSECT (SELECT e.cui FROM THE(SELECT e2.cui FROM EQUIPE e2 WHERE e2.numeq = e1.numeq) e2));

A noter que THE désigne la table imbriquée.

double pointage

SELECT e1.cui.numero, e1.cui.nom, e1.cui.prenom FROM THE (SELECT e2.cui FROM EQUIPE e2 WHERE e2.nomeq = 'miammiam') e1;

FROM EQUIPE e2 WHERE e2.nomeq = 'miammiam') e1; SELECT e.numeq, e.nomeq FROM EQUIPE e WHERE e.cui.numero

SELECT e.numeq, e.nomeq FROM EQUIPE e WHERE e.cui.numero IN (SELECT c.numero FROM CUISINIER c WHERE c.prenom = 'Jean';

SELECT c.numero, c.nom, c.prenom FROM CUISINIER c WHERE c.numero IN (SELECT e.cui.numero FROM EQUIPE e WHERE e.nomeq = 'miamiam');

solution universelle : table de connexion

● solution universelle : table de connexion SELECT co.equ.numeq, co.cui.nomeq FROM CONNEXION co WHERE

SELECT co.equ.numeq, co.cui.nomeq FROM CONNEXION co WHERE co.cui.prenom='Jean';

SELECT co.cui.numero, co.cui.nom, co.cui.prenom FROM CONNEXION co WHERE co.equ.nomeq='miammiam';

4 - Modélisation des associations

Dans le modèle relationnel, les associations peuvent donner lieu à l'introduction de clés étrangères ou à de nouvelles tables. Examinons comment se présente la situation pour un modèle objet-relationnel. Nous avons, en effet, des possibilités supplémentaires :

utilisation de structures de données complexes (tables imbriquées notamment)

utilisation de pointeurs

Nous avons à considérer plusieurs types d'associations : les associations binaires : 1:1, 1:N, M:N et les associations n-aires.

associations binaires 1:1

M:N et les associations n-aires. associations binaires 1:1 Dans le modèle relationnel, le schéma correspond

Dans le modèle relationnel, le schéma correspond usuellement à 2 tables ou à 3 tables ; il y a en effet 4 possibilités:

2 tables ou à 3 tables ; il y a en effet 4 possibilités: Dans le

Dans le modèle objet-relationnel, on peut envisager jusqu'à 12 possibilités dont certaines figurent ci-dessous :

associations binaires 1:N Le modèle relationnel offre deux possibilités de représentations : une avec 2

associations binaires 1:N

associations binaires 1:N Le modèle relationnel offre deux possibilités de représentations : une avec 2 tables

Le modèle relationnel offre deux possibilités de représentations : une avec 2 tables et une avec 3 tables :

représentations : une avec 2 tables et une avec 3 tables : Dans le modèle objet-relationnel,

Dans le modèle objet-relationnel, on peut envisager jusqu'à 12 possibilités dont certaines figurent ci-dessous :

12 possibilités dont certaines figurent ci-dessous : On notera notamment la possibilité de tables imbriquées.

On notera notamment la possibilité de tables imbriquées.

associations binaires M:N

de tables imbriquées. associations binaires M:N Le modèle relationnel ne fournit qu'une seule

Le modèle relationnel ne fournit qu'une seule possibilité :

relationnel ne fournit qu'une seule possibilité : Le modèle objet-relationnel, par contre, offre 16 + 4p

Le modèle objet-relationnel, par contre, offre 16 + 4p possibilités où p est le nombre de propriétés de l'association. Parmi celles-ci :

de propriétés de l'association. Parmi celles-ci : associations n-aires Nous ne traiterons pas complètement ce

associations n-aires

Nous ne traiterons pas complètement ce cas que l'on peut aisément imaginer à la lumière des cas précédents. On démontre que le nombre

de possibilités de représentations dans le modèle objet-relationnel est de (3n + 2 + 2p)2 n-1 où n est le nombre de tables du modèle entité- association impliquées et p le nombre de propriétés de l'association.

exemple : considérons le modèle relationnel suivant issu du modèle E-R :

le modèle relationnel suivant issu du modèle E-R : Voici quelques solutions offertes par le modèle

Voici quelques solutions offertes par le modèle objet-relationnel :

le modèle relationnel suivant issu du modèle E-R : Voici quelques solutions offertes par le modèle

SQL3

1. Introduction

2. Les types de données définis par les utilisateurs

Contenu :

3. Les tables

4. Les constructeurs de type

5. Méthodes

6.

Héritage

7.

Triggers

1. Introduction

La normalisation du langage de requête SQL est pilotée par le groupe ISO/IEC JTC1/SC 21/WG3 DBL. Les travaux de ce groupe sont résumés ci-dessous :

SQL2 : 1 document de référence

SQL3 : 9 composants :

SQL/Framework : cadre général SQL/Foundation : fondements essentiels SQL/CLI : interface client SQL/PSM : procédures stockées SQL/Bindings : intégration dans les langages classiques SQL/Transaction : gestion des transactions SQL/Temporal : gestion du temps SQL/MED : accès aux données externes SQL/OBJ : intégration aux langages objet

Cette normalisation est issue d'une riche historique rappelée ici pour mémoire :

SEQUEL 1 (1974) de System R (IBM) SEQUEL 2 (1977)

SQL1 (ANSI : 1986 ; ISO : 1987 ; révision en 1989 ; tests de validation effectués par le NIST - National Institute of Standards and Technology) SQL2 (ou SQL92, 1992) : 600 pages de spécification SQL3 (SQL99, 1999) : 1500 pages de spécification SQL4 : travaux démarrés en 2001

Les SGBD qui suivent les prescriptions de SQL3 sont appelés SGBD "Objet-Relationnel". Nous n'avons pas d'autres définition, en effet, de ce qu'est un SGBD Objet-Relationnel. Il faut toutefois remarquer que si l'on s'en tient strictement à cette définition, il n'existe pratiquement pas de SGBD Objet-Relationnel !. Mais il existe des SGBD s'en rapprochant : Oracle8-9+, Informix9+ notamment. Les principes généraux de SQL3 sont les suivants :

SQL3 veut incorporer l'objet tout en gardant les acquis du modèle relationnel (et de SQL2). Notamment le concept de relation (table) reste central.

SQL3 s'appuie sur des données fortement typées (type = attributs + méthodes). Le processus de création d'éléments

d'une base de données comporte 3 étapes : création des types nécessaires ; création d'éléments conformément à ces types ; insertion de ces éléments dans des tables existantes (si ces éléments sont des objets, ils deviennent alors automatiquement persistants).

SQL3 reprend tous les acquis de SQL2 et notamment les types prédéfinis (considérés comme atomiques) : DECIMAL,

FLOAT, INT,

caractère), BLOB (LOB de type binaire : une image par exemple), BFILE (fichier).

et aussi les types des objets "grands" comme LOB (Long OBject) comportant CLOB (LOB de type

SQL3 permet (nouveauté !) la création de types par les utilisateurs. Il en existe 2 catégories : le type DISTINCT, et le TAD (Type Abstrait de Données, en anglais ADT) de nature complexe.

On suppose dans tout ce qui suit que le lecteur a une bonne connaissance de SQL2.

2 - Les types de données définis par les utilisateurs

Dans SQL2, pour le modèle relationnel, les types de données sont prédéfinis : CHAR, VARCHAR, NUMBER, DATE,

Dans SQL3, pour le modèle objet-relationnel, des types nouveaux peuvent être définis par les utilisateurs : le type DISTINCT et les TAD. Les TAD se subdivisent en TAD littéral et TAD objet.

Type DISTINCT

Ce type permet une personnalisation des données. Ainsi, un prix d'achat et un prix de vente peuvent s'exprimer par le type prédéfini DOUBLE PRECISION. Mais si l'on veut caractériser ces deux entités (et les "distinguer") , on peut "redéfinir" DOUBLE PRECISION en créant deux "sous-types" :

CREATE DISTINCT TYPE pachat_t AS DOUBLE PRECISION; CREATE DISTINCT TYPE pvente_t AS DOUBLE PRECSION; CREATE TABLE Produit1 (

numP

VARCHAR(10),

pa

pachat_t,

pv

pvente_t );

Dans l'écriture précédente, des conventions sont implicitement respectées : les noms des tables débute par une lettre majuscule et un type est déclaré avec un suffixe "_t" et son nom débute avec une lettre minuscule. Un tuple, de même que son schéma, est défini entre parenthèses.

TAD littéral

Les TAD littéraux portent sur les colonnes des tables relationnelles. On peut regrouper par exemple deux colonnes (dont les champs correspondent à des types différents) en définissant un type pour ce regroupement.

exemple : En reprenant l'exemple précédent, où la table Produit1 possède 3 champs (3 colonnes), on peut regrouper les deux champs pa et pv en définissant un nouveau type :

CREATE TYPE deuxPrix_t ( achat pachat_t, vente pvente_t ); CREATE TABLE Produit2 ( numP VARCHAR(10), prix deuxPrix_t ); SELECT p.numP, p.prix.achat FROM Produit2 p WHERE p.prix.vente > 100;

TAD objet

Contrairement aux TAD précédents, les TAD objet concernent les lignes des tables, c'est à dire les tuples. Le mot clé correspondant est ROW.

exemple :

CREATE TYPE adresse_t (

num

VARCHAR(6),

voie

VARCHAR(40),

ville

VARCHAR(30),

codepostal

INT);

CREATE ROW TYPE personne_t(

numSS

INT,

nom

VARCHAR(30),

prenom

VARCHAR(30),

adresse

adresse_t);

CREATE TABLE Personne OF personne_t(PRIMARY KEY numSS); SELECT p.nom, p.prenom, p.adresse FROM Personne p WHERE p.adresse.codepostal=80170;

Cette sorte de TAD est appelée "objet" dans la mesure où les lignes d'une table peuvent être considérées comme des objets et peuvent (voir plus loin) être référencées comme une entité indépendante, la référence jouant, en quelque sorte le rôle d'un identifiant d'objet mais n'est toutefois pas identique à un oid. Le type ROW explicité plus loin peut aussi être considéré comme représentant un objet.

3 - Les tables

Les tables restent centrales dans SQL3. Tout ce qui concerne les tables en SQL2 est valable en SQL3 (c'est la moindre des choses !).

On peut toujours créer des tables relationnelles classiques ou des tables relationnelles en NF2 ou encore des tables d'objets.

tables relationnelles classiques

exemple :

CREATE TABLE Personne ( nom VARCHAR(30), prenom VARCHAR(30), telephone NUMBER) ;

tables relationnelles en NF2

Elles peuvent être créées en utilisant des constructeurs de type comme ROW() ou LIST()

exemple :

CREATE TYPE adresse_t(num VARCHAR(5), voie VARCHAR(30), ville VARCHAR(30), codepostal INT); CREATE TABLE Personne (

numero

INT,

adresse

adresse_t,

identité

ROW(nom VARCHAR(30), prenom

VARCHAR(30)),

postes

LIST(ROW(bureau INT, tel VARCHAR(10)))

PRIMARY KEY numero);

tables d'objets

Bien que le mot objet n'existe pas dans la syntaxe SQL3, il est implicitement présent dans le modèle lorsque l'on utilise le mot clé OF.

exemple :

CREATE ROW TYPE personne_t (

nom

VARCHAR(30),

prenom VARCHAR(30),

telephone

NUMBER) ;

CREATE TABLE Personne OF personne_t (PRIMARY KEY nom) ;

Dans ce cas, toute instance de la table possède un oid connu du système.

4 - Les constructeurs de type

Comme leur nom l'indiquent, ils servent à construire des types donnés. Nous en avons vu un exemple précédemment avec ROW() et LIST(). Il existe trois catégories de constructeurs de types :

le constructeur ROW qui permet de regrouper un nombre fixe de champs de types différents : le type obtenu est donc un tuple.

les constructeurs de collection : SET, LIST, MULTISET qui permettent de regrouper plusieurs éléments de même type

le constructeur REF qui permet de définir des référence (pointeurs) vers des objets.

constructeur ROW

Il est assez naturel d'emploi et est équivalent à la déclaration ROW TYPE sauf que ROW() s'utilise à l'intérieur de la création d'une table :

exemple :

CREATE ROW TYPE adresse_t (

num

VARCHAR(5),

voie

VARCHAR(30),

ville

VARCHAR(30),

codepostal

INT);

CREATE ROW TYPE identite_t(

nom

VARCHAR(30),

prenom

VARCHAR(30));

CREATE TYPE Personne (

numero

INT,

identite

identite_t,

adresse

adress_t);

est équivalent à

CREATE TYPE personne_t (

numero

INT,

identite

ROW(

nom VARCHAR(30),

prenom

VARCHAR(30)),

 

adresse

ROW(

 

num

VARCHAR(5),

voie

VARCHAR(30),

ville

VARCHAR(30),

codepostal

INT)

);

Le constructeur peut s'utiliser lors d'une instanciation.

exemple : reprenons l'exemple précédent

CREATE TABLE Personne OF personne_t; INSERT INTO Personne VALUES (

);

'1234',

ROW(

 

'DUPONT',

'Aristide'),

ROW(

 

'13',

'bd Saint-Michel', 'PARIS',

'75005')

Dans les requêtes, il faudra utiliser la notation "." pour sélectionner des champs particuliers :

SELECT p.identite.nom, p.adresse.codepostal FROM Personne p WHERE p.adresse.ville = "PARIS';

constructeurs de collections

Une collection contient des éléments de même type (contrairement au ROW). SQL3 définit 3 constructeurs de collection :

au ROW). SQL3 définit 3 constructeurs de collection : L'utilisation des constructeurs est très naturelle.

L'utilisation des constructeurs est très naturelle.

exemple :

CREATE ROW TYPE adresse_t (

num

VARCHAR(5),

voie

VARCHAR(30),

codepostal

INTEGER

ville

VARCHAR(30),

);

CREATE TABLE Annuaire (

identite

ROW(nom VARCHAR(30), prenom

VARCHAR(30)) NOT NULL,

domiciles

LIST(adresse_t),

hobbies

SET(VARCHAR(50))

); INSERT INTO Annuaire VALUES ( ROW ('DUPONT', 'Aristide'), LIST(

ROW( '14', 'bd Saint-Michel', '75005', 'PARIS')::adresse_t, ROW( '13', 'rue André Chénier', '80000', 'AMIENS')::adresse_t),

SET('Tennis','Guitare','Sudoku')

);

Il existe aussi une écriture plus simple pour la clause INSERT :

INSERT INTO Annuaire VALUES (('DUPONT', 'Aristide'),(ROW( '14', 'bd Saint-Michel', '75005', 'PARIS'), ROW( '13', 'rue André Chénier', '80000', 'AMIENS')), ('Tennis','Guitare','Sudoku'));

Quelques opérateurs sont utilisés pour les collections : IN, NOT IN, CARDINALITY. IN et NOT IN permettent de savoir si un éléments figure dans une collection. CARDINALITY donne simplement le nombre d'éléments d'une collection.

exemple :

SELECT p.identite.nom, p.identite.prenom FROM Annuaire p WHERE 'Sudoku' IN p.hobbies; SELECT p.identite.nom, p.identite.prenom, CARDINALITY(p.hobbies) FROM Annuaire p WHERE 'Sudoku' IN p.hobbies;

Constructeur de référence

Rappelons qu'un élément est considéré comme un objet dès qu'il est placé dans une table avec OF. Un objet possède un oid (identifiant) unique qui est généré automatiquement par le système. Rappelons aussi qu'il est immuable, non réutilisable après disparition de l'objet correspondant.

Dans SQL3, l'oid d'un objet de type T est référencé par REF(T). Contrairement au modèle O-O, une référence à un objet peut être affichée dans le modèle O-R. Une référence peut être déclarée dans un type ou dans une table.

exemple : supposons deux types définis a priori, un type personne et un type equipe_t (on suppose qu'une personne du type personne_t correspond à une seule équipe du type equipe_t. On désire relier ces deux types par une référence :

On désire relier ces deux types par une référence : CREATE OR REPLACE BODY TYPE personne_t

CREATE OR REPLACE BODY TYPE personne_t (

nom

VARCHAR(30),

prenom

VARCHAR(30),

affectation

REF(equipe_t));

On peut aussi utiliser le constructeur REF() directement dans la création d'une table.

exemple :

CREATE TABLE binome (

personne1

REF(personne_t),

personne2

REF(personne_t));

Considérons maintenant les deux requêtes suivantes :

SELECT p.affectation FROM Personne p WHERE p.nom = 'Dupont'; SELECT p.affectation->nomeq FROM Personne p WHERE p.nom = "Dupont';

La première requête fournira seulement l'adresse de l'équipe correspondant à la personne 'Dupont' ce qui n'est pas en général très utile.

La seconde requête fournira le nom de l'équipe à laquelle est affecté la personne 'Dupont'. Elle est équivalente à :

SELECT e.nomeq FROM Personne p, Equipe e

WHERE

p.nom = 'Dupont'

AND

REF(e) = p.affectation;

5 - Méthodes

Nous avons signalé que SQL3 est basé sur un typage fort, c'est à dire que le type inclut les attributs mais aussi les méthodes. Comment SQL3 définit-il les méthodes ?

Il faut distinguer la déclaration de la définition. La définition s'effectue à la création du type selon la syntaxe évidente :

CREATE TYPE nomtype_t ( attributs déclaration ou définition des méthodes);

La définition des méthodes peut se faire lors de la création du type (CREATE) comme la syntaxe précédente le montre ou lorsque l'on modifie le type (REPLACE). La définition d'une méthode nécessite un langage de programmation qui peut être interne( c'est le cas de PL/SQL dans Oracle) ou externe (C ou C++ pu Java).

exemple : le type personne_t contient la méthode personne_t() qui ajoute une personne (c'est un constructeur de type !).

CREATE TYPE personne_t ( nom VARCHAR(30), prenom VARCHAR(30),

FUNCTION personne_t( :nom VARCHAR(30), :prenom VARCHAR(30)) RETURNS personne_t;

:p personne_t;

BEGIN :p := personne_t(); :p.nom := :nom; :p.prenom := :prenom; RETURN :p;

END;);

/* déclaration locale */

/* constructeur */

La méthode personne_t() est ici définie complètement dans le type. On pourrait seulement la déclarer :

CREATE TYPE personne_t (

nom

VARCHAR(30),

prenom

VARCHAR(30),

FUNCTION personne_t( :nom VARCHAR(30), :prenom VARCHAR(30) RETURNS personne_t); );

Evidemment il faudra définir, dans ce dernier cas la fonction personne_t() ailleurs, c'est à dire hors du type personne_t.

SQL3 fournit aussi un certain nombre de fonctions utilitaires comme des fonctions de comparaison et des fonctions de conversion que nous n'explicitons pas ici.

6 - Héritage

On peut considérer deux types d'héritages : l'héritage de type et l'héritage de table. L'héritage de type permet de définir des sous-types avec le mot clé UNDER.

exemple :

CREATE ROW TYPE personne_t (

nom

VARCHAR(30),

prenom

VARCHAR(30));

CREATE ROW TYPE professeur_t UNDER personne_t (

categorie VARCHAR(10), discipline VARCHAR(20));

CREATE ROW TYPE etudiant_t UNDER personne_t (

diplôme

VARCHAR(10),

numero

INTEGER);

On notera qu'il suffit d'ajouter les propriétés nouvelles. L'héritage de table s'effectue également avec le mot clé UNDER

exemple :

CREATE TABLE Personne (

nom

VARCHAR(30),

prenom

VARCHAR(30));

CREATE TABLE Professeur UNDER Personne (

categorie

VARCHAR(10),

discipline

VARCHAR(20));

CREATE TABLE Etudiant UNDER Personne (

diplôme

VARCHAR(10),

numero

INTEGER);

7 - Triggers

Un trigger (ou déclencheur) exécute un programme en fonction d'événements particuliers, notamment une mise à jour par INSERT, UPDATE, DELETE).Les caractéristiques d'un trigger sont les suivantes :

un trigger est associé à une table

un trigger comprend deux sections : la description de l'événement déclencheur et la description du traitement à effectuer

il y a deux catégories de triggers : le "row trigger" qui est un déclencheur pour un événement particulier (mise à jour d'un tuple par exemple) et le "statement trigger" qui est un déclencheur pour une série de mises à jour

un trigger ne peut effectuer des manipulations sur la table qui lui est associée (IMPORTANT !)

La syntaxe de définition d'un trigger est la suivante :

CREATE TRIGGER <nom_trigger>

(AFTER | BEFORE) <événement> ON <nom de table> FOR EACH ROW BEGIN --- actions --- END;

exemple :

CREATE OR REPLACE TYPE equipe_t (

numeq

NUMBER,

nomeq VARCHAR(30),

effectif

NUMBER) ;

CREATE OR REPLACE TYPE cuisinier_t AS OBJECT (

numero

NUMBER,

nom

VARCHAR(30),

prenom VARCHAR(30),

affectation

NUMBER) .

CREATE TABLE Equipe OF equipe_t (CONSTRAINT knumeq PRIMARY KEY(numeq) ) ;

CREATE TABLE Cuisinier OF cuisinier_t ( CONSTRAINT knumero PRIMARY KEY(numero), CONSTRAINT fknumeq FOREIGN KEY(affectation) REFERENCES Equipe(numeq) );

La création de deux tables Cuisinier et Equipe permet d'obtenir une situation analogue à celle-ci :

permet d'obtenir une situation analogue à celle-ci : Créons maintenant des triggers (de type row) sur

Créons maintenant des triggers (de type row) sur la table Cuisinier : un trigger TIcuisinier pour l'ajout d'un cuisinier, un trigger TDcuisinier pour la suppression d'un cuisinier, un trigger TUcuisinier pour une mise à jour d'un cuisinier existant.

CREATE OR REPLACE TRIGGER TIcuisinier AFTER INSERT ON Cuisinier FOR EACH ROW BEGIN UPDATE equipe SET effectif = effectif + 1 WHERE numeq = NEW.affectation;

END;

CREATE OR REPLACE TRIGGER TDcuisinier AFTER DELETE ON Cuisinier FOR EACH ROW BEGIN

UPDATE equipe SET effectif = effectif - 1

WHERE numeqq = :OLD.affectation;

END; CREATE OR REPLACE TRIGGER TUcuisinier AFTER UPDATE OF affectation ON Cuisinier FOR EACH ROW BEGIN UPDATE equipe SET effectif = effectif - 1 WHERE numeq = :OLD.affectation; UPDATE equipe SET effectif = effectif + 1 WHERE numeq = :NEW.affectation;

END;

On notera que c'est la table Equipe qui est affectée par l'action du trigger et non pas la table Cuisinier (les triggers sont associés à cette dernière table).

Une autre formulation de la création des triggers est donnée ci-dessous :

CREATE OR REPLACE TRIGGER TIDUcuisinier AFTER INSERT OR DELETE OR UPDATE OF affectation ON Cuisinier FOR EACH ROW BEGIN

IF (INSERTING) THEN UPDATE Equipe SET effectif = effectif + 1 WHERE numeq = :NEW.affectation; END IF; IF (DELETING) THEN UPDATE Equipe SET effectif = effectif – 1 WHERE numeq = :OLD.affectation; END IF; IF (UPDATING(‘affectation’)) THEN UPDATE Equipe SET effectif = effectif – 1 WHERE numeq = :OLD.affectation; UPDATE Equipe SET effectif = effectif + 1 WHERE numeq = :NEW.affectation; END IF; END;

exemple : nous procédons ici à la mise à jour automatique de plusieurs tables (Cuisinier, Equipe) à partir d'une vue (Personnel) . Une vue se crée comme en SQL2.

CREATE VIEW Personnel AS SELECT c.numero, c.nom, c.prenom, c.affectation, e.nomeq, e.effectif FROM Cuisinier c, Equipe e WHERE c.affectation = e.numeq; CREATE TRIGGER TIpersonnel INSTEAD OF INSERT ON Personnel BEGIN INSERT INTO Cuisinier VALUES ( :NEW.numero, :NEW.nom, :NEW.prenom, :NEW.affectation); UPDATE Equipe SET effectif = effectif + 1 WHERE numeq = :NEW.affectation; END; INSERT INTO Personnel VALUES (31, 'DUCHEMIN', 'Berthe', 4);

Oracle

Contenu :

1. Introduction

2. Types abstraits de données

3 - Notions de PL/SQL

<chapitre encore en chantier>

1. Introduction

On considère parfois Oracle comme le premier SGBD Relationnel (1979). Toujours est-il qu'il s'est maintenu jusqu'à aujourd'hui à la première place des systèmes commercialisés. Il a su évoluer du relationnel vers l'Objet-Relationnel depuis la version 8 complétée par la version 8i qui intègre des fonctionnalités Web et multimédia. La version 9i intègre de nouveaux types de données (XML) et permet la construction d'entrepôts de données. LA version actuelle est 10i.

Il possède l'intérêt majeur d'être implémentable sur les deux principaux systèmes d'exploitation Unix (et Linux) et Windows. Il est évidemment concurrencé aujourd'hui par des SGBD libres et OpenSource.

Par rapport aux 13 règles définissant un SGBD Objet, le produit Oracle se positionne de la manière suivante (on se base ici sur Oracle8i) :

objets composites : les types abstraits de données (TAD) définis par l'utilisateur permettent de définir des objets composites.

identités d'objet : le concept d'identifiant existe

encapsulation : oui, mais

classes, types, méthodes : TAD et tables permettent le concept

héritage : hum

surcharge et liaison dynamique : oui pour la surcharge

extensibilité : oui

langage de programmation OO : PL/SQL (limité) en interne et C++ et Java en externe.

persistance des données : tout objet stocké dans une base Oracle est persistant.

grande quantité de données : la version 8 peut stocker théoriquement 512x10 15 octets.

partage des données et gestion d ela concurrence : Oracle propose une architecture NCA (Network Computing Architecture) permettant d'accueillir jusqu'à 15 000 utilisateurs.

fiabilité des données : déclaration de contraintes dans les tables ; déclenchement par triggers.

langage de requête : SQL3 partiellement.

On voit donc que Oracle 8i et ses successeurs intègrent un nombre non négligeable de concepts du modèle objet. Dans ce qui suit, on ne s'intéressera qu'aux apports d'Oracle par rapport au modèle relationnel et à

SQL2.

2 - Types abstraits de données

Oracle 8 permet la création de TAD spécifiques que SQL3 ne prévoit pas :

le type OBJET

les types du genre " COLLECTION " : VARRAY et NESTED TABLE

Le type OBJET

Il est défini de la façon suivante :

CREATE TYPE <nom du type> AS OBJECT ( attribut 1 attribut 2 --------------- attribut n

CREATE TYPE <nom du type> AS OBJECT ( attribut 1 attribut 2 --------------- attribut n
CREATE TYPE <nom du type> AS OBJECT ( attribut 1 attribut 2 --------------- attribut n
CREATE TYPE <nom du type> AS OBJECT ( attribut 1 attribut 2 --------------- attribut n

DATATYPE,

DATATYPE,

------------,

DATATYPE,

[définition de méthode]

);

Les méthodes sont des fonctions ou des procédures qui sont stockées dans la base (PL/SQL, Java) ou à l'extérieur de la base (langage C).

exemples :

CREATE TYPE personne_t AS OBJECT (

nom

VARCHAR(30),

telephone

VARCHAR(20) );

CREATE TYPE article_t AS OBJECT (

code

VARCHAR(30),

qte

NUMBER,

pu

NUMBER(10,2) );

On peut ensuite utiliser le mot clé OF pour utiliser ce type :

CREATE TABLE Personne OF personne_t; CREATE TABLE Article OF article_t;

Il faut faire une distinction entre les tables typées et les tables non typées. Une table typée est déclarée à l'aide d'un Tad comme dans l'exemple précédent (CREATE TABLE <nom_table> OF <nom_type>). Un table

non typée est définie directement (CREATE TABLE <nom_table> (

les lignes de la table sont des objets possédant un oid. Dans les tables non typées, les lignes de la table ne sont pas des objets (et ne possèdent pas d'oid). On peut extraire l'oid avec REF() (SELECT REF(e) FROM <nom_table> e) ; si la table est non typée, une erreur est retournée.

attributs

)).

Dans les tables typées,

Le type COLLECTION

Il permet la création d'attributs multivalués et correspond aux deux possibilités VARRAY et NESTED TABLE.

VARRAY

tableau à 1 dimension d'éléments du même type ; le tableau a une taille variable.

CREATE TYPE <nom1 du type> AS ARRAY(nmax) OF <nom2 de type>

exemple : répertoire de clients pouvant avoir chacun 3 adresses au maximum

CREATE TYPE client_adr_t AS OBJECT (

num

voie VARCHAR(30), ville VARCHAR(30),

cp

NUMBER,

NUMBER) ;

CREATE TYPE adresses_t AS VARRAY(3) OF client_adr_t; CREATE TYPE client_type AS OBJECT(

nomclient

VARCHAR(30),

adresses adresses_t); CREATE TABLE Client OF client_type;

NESTED TABLE

Ce type correspond à un ensemble non ordonné et non limité d'éléments de même type

CREATE TYPE <nom1 de type> AS TABLE OF <nom2 de type>

exemple : description d'un stock d'articles

CREATE TYPE article_t AS OBJECT ( nomart VARCHAR(30),

qte

NUMBER,

pu

NUMBER(10,2) );

CREATE TYPE tab_article_t AS TABLE OF article_t ; CREATE TYPE stock_t AS OBJECT ( categorie VARCHAR(30),

liste

tab_article_t);

CREATE TABLE Stock OF stock_t;

exemple : description d'une commande

CREATE TYPE article_t AS OBJECT (

numart

INTEGER;

qtecom

INTEGER);

CREATE type com_article_t AS TABLE OF article_t; CREATE TYPE ligne_com_t AS OBJECT (

numcom

INTEGER,

datecom

DATE,

numcli

INTEGER,

articles

com_article_t);

CREATE TABLE Commande OF ligne_com_t;

3 - Notions de PL/SQL

PL/SQL (Procedural Language / SQL) est une extension de SQL dans le SGBD Oracle.

PL/SQL est structuré en blocs

de SQL dans le SGBD Oracle. PL/SQL est structuré en blocs La section "declare" comprend des

La section "declare" comprend des déclarations concernant les constantes, les variables, les curseurs.

a) variables et constantes

La déclaration suit la syntaxe suivante :

b) curseurs Un curseur désigne un ensemble de tuples destinés à être traités un par

b) curseurs

Un curseur désigne un ensemble de tuples destinés à être traités un par un. La déclaration d'un curseur suit la syntaxe suivante :

La déclaration d'un curseur suit la syntaxe suivante : exemple : CURSOR cuisinier_cur (num NUMBER, name

exemple :

CURSOR cuisinier_cur (num NUMBER, name VARCHAR(30) ) IS SELECT prenom FROM cuisinier WHERE numero = num AND nom = name ;

La section placée entre BEGIN et END comporte principalement des instructions reprenant des ordres de type SQL et des éléments de langages spécifiques.

exemple :

declare maxnum cuisinier.numero%TYPE;

begin

SELECT MAX(numero) INTO maxnum FROM cuisinier; maxnum := maxnum + 1;

end

Noter le signe d'affectation (:=).

PL/SQL possède des structures itératives (boucles) de trois types : indéfinie, "while", "for" :

PL/SQL possède aussi des structures conditionnelles : exemple (heureusement irréel !): IF nomsalarie =

PL/SQL possède aussi des structures conditionnelles :

PL/SQL possède aussi des structures conditionnelles : exemple (heureusement irréel !): IF nomsalarie =

exemple (heureusement irréel !):

IF nomsalarie = 'TARTEMPION' THEN salaire := salaire*2; ELSEIF salaire > 10000 THEN salaire := salaie/2;

ELSE salaire := salaire*3; ENDIF;

Examinons maintenant sur un exemple l'emploi de curseurs.

exemple : tri, dans une table emploi, des salariés dont le salaire est inférieur à 2000 et augmentation des salaires de ceux-ci de 100 :

declare CURSOR salcur IS

SELECT * FROM emploi WHERE sal < 2000; salarie emploi%ROWTYPE; begin OPEN salcur; LOOP FETCH salcur INTO salarie; UPDATE emploi SET sal := sal + 100 WHERE numsal = salarie.numsal; EXIT WHEN salcur%NOTFOUND; END LOOP; end;

La section begin

"exception". Une exception est un événement "non attendu" ; PL/SQL prévoit les actions à entreprendre en ce cas. Oracle fournit des exceptions prédéfinies :

end

peut aussi contenir des exceptions que l'on place dans une zone spéciale

NO_DATA_FOUND : pas de résultat à une requête TOO_MANY_ROWS : plus d elignes qu'il n'est prévu CURSOR_ALREADY_OPEN : curseur déjà ouvert INVALID_CURSOR : curseur invalide (en principe non déclaré).

L'utilisateur peut aussi définir ses propres exceptions ; il faut alors les déclarer dans la section "declare" par exception_i EXCEPTION; puis définir un traitement dans la zone "exception" :

begin

-----------

exception WHEN <exception_1> THEN <instructions_1>;

------------------------------------------------------

WHEN <exception_n> THEN <instructions_n>;

end;

PL/SQL permet de définir et d'utiliser des procédures et des fonctions :

exemple : CREATE TABLE T (num1 INTEGER, num2 INTEGER); CREATE OR REPLACE PROCEDURE remplir(IN x

exemple :

CREATE TABLE T (num1 INTEGER, num2 INTEGER); CREATE OR REPLACE PROCEDURE remplir(IN x NUMBER, OUT y NUMBER, INOUT z NUMBER) AS BEGIN

y := x*z;

z := z*z;

INSERT INTO VALUES (x, z);

END;

declare

a NUMBER;

b NUMBER;

begin

a := 5;

b := 10;

remplir (2, a, b);

a

:= a*b;

end;

IN signifie "lecture seule", OUT signifie "écriture seule", INOUT signifie "lecture-écriture".

Après appel de la procédure, a = 20, b = 100 puis a devient 2000.

G. GARDARIN

Christian SOUTOU

EL MASRI, NAVATHE

Bibliographie

Bases de Données, Objet et Relationnel

Objet-relationnel sous Oracle 8, Modélisation avec UML

Fundamentals of Database Systems

Eyrolles

Eyrolles

International

Edition

Webographie

Gamache - Modèle étape : du relationnel vers le modèle objet-relationnel, via le navigationnel - Chapitre 3

Gamache - Modèle Objet-Relationnel - Module 4

Gardarin : l'objet-relationnel

SQL3 Object Model