Sunteți pe pagina 1din 55

Contraintes du MOR, implémentation des associations,

interrogation et collections
Exemple: Schéma OR pour l'association 1-1 ou (1..1 – 1..1)

Stage Etudiant
noS* matE*
sujetS nomE
@etudiant_t ageE
effectueE

Create Type etudiant_t as Object ( matE int, nomE varchar(50), age int) /
Create Type stage_t as Object ( noS int, sujetS varchar(25), effectueE REF
etudiant_t) /
Create Table Etudiant of etudiant_t (Constraint pk_matE Primary key (matE));
Create Table Stage of stage_t (constraint pk_Stage Primary key (noS),
Une table et non un type
Constraint c_effectueE Check (effectueE IS NOT NULL),
Constraint s_effectue effectueE SCOPE IS Etudiant);
*** La multiplicité n'est pas validée avec cette spécification de la table Stage.
Est-ce que ce lien mono et externe est équivalent à l'association?
¾ Lien est toujours valué : tout stage est donc associé à un étudiant.

¾ Est-ce que l'ajout d'un étudiant peut violer la multiplicité obligatoirement 1


du côté Stage?
‰ Non. Il peut y avoir plusieurs stages associés à un seul étudiant. Il faut
donc valider cette multiplicité par un trigger After Insert sur la table
Stage.

¾ Est-ce que l'ajout d'un stage implique que ce dernier est obligatoirement
associé à un seul étudiant?
‰ Non. Il faudra à l'ajout d'un stage ajouter aussi un étudiant dans la
même transaction et ensuite s'en assurer par un trigger Before Insert
associé à Stage et finalement faire un commit.
Cohérence et unicité de la multiplicité NOT NULL du lien externe

¾ Cohérence du parent non renforcée: Un étudiant peut être supprimé


même s'il effectue présentement un stage.

Create Table Stage of stage_t (Constraint pk_Stage Primary key (noS),


Constraint c_effectueE Check (effectueE IS NOT NULL),
Constraint s_effectue effectueE SCOPE IS Etudiant));

La suppression d'un étudiant est faite en dépit de la contrainte du SCOPE IS.

Si effectueE avait été contrainte par REFERENCES Etudiant, la suppression


aurait été bloquée et la cohérence du parent assurée.

¾ Cohérence de la table enfant (Stage)


idem
Suite … Unicité de la l'attribut ref ?

¾ Contrainte d'unicité sur la référence effectueE ? Deux stages distincts ne


peuvent pas être attribués au même étudiant.

Validation avec une contrainte Unique sur la Ref ?


Create Table Stage of stage_t (
Constraint pk_Stage Primary key (noS),
Constraint c_effectueE Check (effectueE IS NOT NULL),
Constraint s_effectue effectueE SCOPE IS Etudiant,
Constraint U_refE UNIQUE (effectueE) Un attribut de type
); REF ne peut pas
être contraint par
Unique
***ERREUR à la ligne…. De la contrainte U_refE!

Impossible de déclarer une contrainte Unique sur un attribut de type REF.


Suite … Unicité de la multiplicité de Etudiant

2 stages distincts ne peuvent pas être attribués au même étudiant :


Create trigger tr_UniqueEffectue BEFORE Insert or Update of noS On Stage
for each row -- trigger associé à Stage
Declare
res number := 0;
Begin
Select Count(*) into res From Stage s
Where s.effectueE = :new.effectueE;
If res !=0 then
Raise_Application_Error ( -20300, 'lien ayant déjà 1 stage/etudiant ') ;
End If;
End;
/
Sans le trigger, la multiplicité n'est pas vérifiable pour l'heure!
Autre écriture du trigger

Le trigger suivant est en principe plus rapide que le précédent


Create Or Replace trigger tr_UniqueEffectue BEFORE Insert or Update of noS On
Stage for each row
Declare
nbStage int ;
stage_existe exception;
Begin
Select 1 into nbStage from Stage s Where s.noS = :new.noS;
Raise stage_Existe;
Exception
When NO_DATA_FOUND Then Raise_Application_Error(-20450, ' invalide');
When stage_existe Then Raise_Apllication_Error (-20300, ' stage en cours');
End;
Mnav: Association 1-1 : Initialisation lien monovalué

Stage Etudiant
noS* matE*
sujetS nomE
@etudiant_t ageE
effectueE

Create Table Etudiant of etudiant_t (Constraint pk_matE Primary key (matE));


Create Table Stage of stage_t (constraint pk_Stage Primary key (noS),
Constraint c_effectueE Check (effectueE IS NOT NULL),
Constraint s_effectue effectueE References Etudiant);
Initialisation de l'attribut effectueE pour établir l'association avec :
Insert into Etudiant values (etudiant_t (3, 'Lynda', 23 ));
Insert into Stage values( stage_t(100, (Select REF(x) From Etudiant x
Where x.matE = 3)));
La fonction REF() retourne une référence à l'objet associé à la variable d'objet x
Mnav: Association 1-1 : Modification du lien monovalué

Stage Etudiant
noS* matE*
sujetS nomE
@etudiant_t ageE
effectueE

Modification du lien: le stage change de titulaire pour celui de l'étudiant 75


Update Stage s
SET s.effectueE = ( Select Ref(e) From Etudiant e Where e.matE = 75);
Where s.noS = 150;
Suppression de la REF (cas où effecteuE n,est pas contrainte par un NOT NULL)
Update Stage s Set s.effectueE = null Where s.noS = 150 ;
Association 1 - * du Mnav en OR (version lien interne vers une collection)

Pilote
Implémentation par un lien interne multi vers la
noP*
structure interne (le type) entr_t pour Entrainement.
nomP
Un lien interne particulier conduit à plusieurs objets
gradeP imbriqués de type entr_t.
lesEntr Devient un objet-colonne
entr_t
codeE*
dateE Formulation relationnelle théorique (NF2):
regionE Entrainement ( codeE*, dateE, regionE)
Pilote(noP*, nomP, gradeP, lesEntr) (avec un attribut complexe
de type ensemble ou collection)
En OR:
Create Type entr_t as Object (codeE int, dateE Date, regionE varchar2(5))
/
Suite… Association 1-* (table imbriquée)

Une table imbriquée dans une table PARENT n'a qu'un seul attribut qui peut
être complexe comme un objet de colonne (conférant indirectement plusieurs
attributs à la table imbriquée.)
• Création du type de la table imbriquée (type de la collection):
Create Type lesEntr_t AS TABLE OF entr_t -- type de l'ensemble
Peut être lu comme un ensemble
/
d'objets-colonnes définis avec le
OU si le type de l'élément est simple : type entr_t

Create Type lesEntr_t AS TABLE OF varchar2(50)


/
• Création du type de la classe Pilote:
Create Type pilote_t as Object (noP int, nomP varchar2(35), gradeP char(1),
lesEntr lesEntr_t) / -- lesEntr a un type de collection i.e. une table imbriquée.
Le nom de l'attribut de collection et son type
Association 1-* Création des tables d'objets

• Création de la table TYPÉE Pilote contenant la table imbriquée:

Create Table Pilote of pilote_t (Constraint pk_Pil Primary Key (noP))


NESTED TABLE lesEntr STORE AS TableLesEntr;
Nom de la table physique utilisée pour
implémenter la table imbriquée, lesRefE

Définition de la colonne (attribut complexe) de Pilote qui forme la table imbriquée. La


clause STORE AS précise le nom de la table externe, soitTableLesEntr utilisée pour
ranger les éléments de l'ensemble lesEntr. Cette table TableLesEntr n'est pas
accessible directement par le DML : Update, Delete et Insert.
Information sur les tables imbriquées

SQL> Describe lesEntr_t ;

lesEntr_t TABLE OF ENTR_T -- la collection est du type table (ensemble)

Name Null? Type


CODEE NUMBER(38)
DATEE DATE
REGIONE VARCHAR2(5)
Association 1-* (avec table non typée)

• Création de la table NON TYPÉE (relationnelle) contenant la table


imbriquée:
Create Table Pilote (noP int,
nomP varchar(50),
gradeP char(1),
lesEntr lesEntr_t, -- attribut complexe

Constraint pk_Pil Primary Key (noP))


NESTED TABLE lesEntr STORE AS TableLesEntr;
Structure LOGIQUE versus structure physique de la table imbriquée

¾ La table imbriquée peut être vue comme une sous-table de la table parent
(hôte), mais son implantation fait appel à une table physique séparée laquelle
ne peut pas être utilisée directement ni pour la sélection, ni pour la mise à jour.
Un objet-
Structure logique : colonne de
type
Pilote : collection
noP*:int nomP:varchar gradeP: char lesEntr : {} contenant
d'autres
objets-
codeE dateE regionE colonnes
50 Jacquet A 1 2-12-98 Sud
2 7-12-98 Sud
60 Vézina B 1 17-11-99 Nord

Cette table contient deux objets (instances) et chacun a un objet colonne de


type collection. Le premier objet-colonne, soit la première collection est formée
d'objets-colonnes de type composé d'attributs élémentaires.
Résumé des types pour déclarer l'objet de type collection (ensemble)
¾ L'attribut complexe lesEntr de type ensemble de la table Pilote a comme
instances des objets-colonnes ayant qu'un seul attribut mais ce dernier
peut être complexe et être construit sur la base de d'autres types simples
ou complexes.
¾ La table Pilote aura donc son type nommé, incluant un attribut pour l'objet
colonne de type collection (ensemble).
• Pilote ===> pilote_t

¾ Dans la représentation graphique tabulaire l'objet-colonne est nommé et


est typé:
‰ lesEntr ===> attribut de type lesEntr_t
‰ lesEntr_t ===> de type TABLE de entr_t (TABLE pour déclarer la notion d'ensemble)
‰ entr_t ===> (codeE : int , dateE : DATE , regionE : int)
Structure interne d'une table contenant une table imbriquée

¾ Les éléments de la table imbriquée sont stockés dans un espace physique distinct de
celui de la table qui la contient.
Chaque table imbriquée (ayant un seul attribut complexe) correspond à une table de stockage
composée des attributs de la table imbriquée plus une colonne cachée qui permet de
matérialiser chaque élément à un tuple parent. L'accès aux éléments de la sous-table
génère une jointure implicite, mais bien réelle.
Colonne cachée
Pilote: noP* nomP gradeP nestedTableID
50 Jacquet A 23F45
60 Vézina B 36A456

TableLesEntr :
nestedTableID codeE dateE regionE
23F45 1 2-12-98 Sud
23F45 2 7-12-98 Sud
36A456 1 17-11-99 Nord
Indexation de la sous-table (externe)

¾ La table imbriquée de type NESTED est une collection (set) ouverte


d'objets (sans oid). Une recherche d'objets dans la table Pilote doit donner
aussi accès aux objets de la table imbriquée associés au tuple-objet
parent.
Pour éviter de parcourir tous les objets (fullscan) de la table imbriquée, il
faut créer un index (particulièrement utile si la table imbriquée est de
grande taille):

¾ L'indexation est faite via la table de stockage physique (de là son nom
apparaissant dans la clause STORE de la création de la table parent.

Création de 2 index avec les attributs de la sous-table:


Create Unique Index regionE_idx ON TableLesEntr (regionE);

Create Unique Index dateE_idx ON TableLesEntr (dateE);


Interrogation d'une table avec une collection

Il ya 2 sortes de sélection possibles:


-Une sélection des objets-colonnes seulement.
- Une sélection des objets de table incorporant un objet-colonne de type collection.

Pilote
noP*
nomP
gradeP
lesEntr
entr_t
codeE*
dateE
regionE
Insertion d'objets dans la table typée Pilote

Insert into Pilote values (pilote_t(50, 'Jacquet', 'A',


lesEntr_t(
entr_t(1, to_Date('2-12-1998', 'dd-mm-yyyy'),'Sud'),
entr_t(2, to_Date('7-12-1998', 'dd-mm-yyyy'), 'Sud')
)));

Insert into Pilote values(pilote_t(60, 'Vézina', 'B',


lesEntr_t(entr_t(1, to_Date('17-11-1999','dd-mm-yyyy'),'Nord')
)));
Vision tabulaire de Pilote

Pilote:
noP* nomP gradeP lesEntr : { }
codeE dateE regionE
50 Jacquet A 1 2-12-98 Sud
2 5-6-04 Sud
60 Vézina B 1 17-11-99 Nord
70 Turgeon A null null null

La table Pilote contient 2 objets de table comprenant un objet-colonne de type


collection (ensemble).

Le 1er objet colonne a une collection composée de 2 instances de OC et le 2e


comprend 1 instance OC.
Recherche dans une table parent ayant une sous-table (Nested)
Il est possible d'accéder aux données d'une collection sans (1) ou avec (2)
Unnest.
1.1- Faire un Select avec l'attribut d'ensemble : quels sont les
entraînements suivis par les pilotes?
SQL> Select p.lesEntr From Pilote p;
LESENTR(CODEE, DATEE, REGIONE)
LESENTR_T(ENTR_T(1, '98-12-02', 'Sud'), ENTR_T(2, '98-12-07', 'Sud'))
LESENTR_T(ENTR_T(1, '99-11-17', 'Nord'))

La réponse est composée de deux objets-colonnes imbriquées dans un autre objet colonne.

Les applications qui exploitent une telle réponse doivent prévoir les structures de réception
appropriées : en PL/SQL c'est le curseur typée avec LesEntr_t. En C c'est une struct . En
C++, une classe, en Java,… dont la définition peut être fournie par l'utilitaire JDBC.
Recherche comportant un attribut et une collection

1.2 - Faire un Select pour obtenir un attribut simple et un attribut d'ensemble:


Quels sont les pilotes (nomP) et leurs entraînements respectifs?
SQL> Select p.nomP, p.lesEntr From Pilote p ;
NOMP LESENTR(CODEE, DATEE, REGIONE)
Jacquet LESENTR_T(ENTR_T(1, '98-12-02', 'Sud'), ENTR_T(2, '98-12-07', 'Sud'))
Vézina LESENTR_T(ENTR_T(1, '99-11-17', 'Nord'))

La réponse est composée de deux objets de table. Le premier ayant deux objets-colonnes
imbriqués.
Affichage des attributs autres que ceux des collections

Quels sont les pilotes de grade A inscrits dans la base?

Select p.noP, p.nomP -- aucun accès à la sous-table


From Pilote p
Where p.gradeP = 'A';

Le résultat est une table en FN1.


Unnesting une collection pour un résultat en FN1
2- Extraction (opération de Unnesting) par la directive TABLE() et non directement comme dans
le cas d'une référence pour obtenir deux instances d'objets-colonnes distincts.

2.1 Listez les pilotes et leurs entraînements ( en FN1):


Select p.noP, e.dateE
From Pilote p, TABLE ( p.lesEntr) e; -- expression de table() est un attribut d'ensemble
NOP DATEE
50 98-12-02
50 98-12-07
60 99-11-17
La sous-table étant unnested (ramenée au premier niveau, il y a jointure de chaque collection
avec l'objet de Pilote. Les données du résultat se présentent comme une table relationnelle en
FN1.

2.2 Quelles sont les numéros de pilote et les dates d'entraînement dans la région Sud?
Les données de la réponse proviennent que de la sous-table:

Select e.dateE
From Pilote p, TABLE ( Select p.lesEntr from Pilote p ) e -- unnesting la sous-table
Where e.regionE = 'Sud' ;
** Restriction : le Select de Table doit retourner une seule collection composé d'un seul
attribut.
Vision tabulaire de Pilote

2.3 Fournir le code (codeE) des entraînements du pilote 50.


alias quasi toujours obligatoire
Select e.codeE -- attribut de la sous-table

From TABLE ( Select p.lesEntr from Pilote p where p.noP = 50) e ;

La sous-requête de TABLE() doit fournir qu'un seul objet-colonne (collection) pour le


unnesting. Le résultat est désigné par l'alias e. L'accès aux données de code.E
fournit le code de la mission d'entraînement le pilote 50.

La sous-requête (THE (en SQL3) ou TABLE (Oracle)) fournit l'objet-colonne (en


bleu) de la sous-table associée au pilote no 50.
Autres interrogations avec la Directive TABLE()

¾ Quel est le no du pilote effectuant l'exercice d'entraînement no 1?


Accès à la sous-table suivi d'un filtre et affichage d'une donnée de la table
Parent. L'accès au pilote est fait suite à un filtre prédicatif sur la sous-table
lesEntr.
Select p.noP
From Pilote p, Table(Select p.lesEntr From Pilote ) e
Where e.codeE = 1;

La requête suivante est interdite, car lesEntr n'est pas un attribut de type
REF.
Select p.noP
From Pilote p
Where p.lesEntr.codeE = 1;
Erreur : unknown identifier
Autres interrogations (suite)

¾ Quels sont les pilotes (fourrnir toute l'information) qui ont eu un


entraînement?

Select p.noP, p.nomP, e.*


From Pilote p, TABLE(d.lesEntr) e ;

¾ Ajoutez aussi les pilotes qui n'ont pas encore eu un entraînement.

Select p.noP, p.nomP, e.*


From Pilote p, TABLE(d.lesEntr) (+) e ;

* Le (+) sous-tend une jointure externe.


Ajout et mise à jour d'un élément dans une collection

¾ L'ajout d'un élément suppose en premier le repérage de l'objet parent et


ensuite le repérage de l'objet colonne de ce parent:

Par exemple: ajout d'un entraînement [5, '24-10-2004', 'Est'] au pilote 60:

Insert into Table(Select p.lesEntr From Pilote p Where p.noP = 60)


Values (entr_t(5, '24-10-2004', 'Est'));

¾ Mise à jour du pilote 60 dont la mission 1 a été effectuée au 'Sud' et non


au 'Nord'.

Update Table (Select p.lesEntr From Pilote Where p.noP = 60) e


SET e.regionE = 'Nord';
Attention: une seule collection par UPDATE peut être modifiée!
Plusieurs collections dans une table typée (ou non)

Usine:
noU* villeU lesAteliersIn lesAteliersEx
tel chef specialite chefE villeE
100 Québec 456 Dion soudure argon Jean Qc
345 Morin coupe laser Luc Mtl
200 Montréal 327 Joliot pliage acier Kevin Lévis
678 Curie structure

Deux sous-tables imbriquées dans la table Usine, chacune a une taille indépendante
de l'autre:
L'objet usine no 200 a deux collections: la 1ère a une taille de 2 et la 2è avec une
taille de 1 (pour ce moment).

Chaque collection peut avoir son type : NESTED ou VARRAY.


Schéma d'une table avec plusieurs collections

Le schéma comprend les types et la table :

¾ Create type atelierIn_t as Object (tel varchar2(12), chef varchar2(50), specialite


varchar2(50))
/

¾ Create type lesAteliersIn_t as TABLE OF atelierIn_t /

¾ Create type atelierEx_t as object (chefE varchar2(12), villeE varchar2(50)) /

¾ Create type lesAteliersEx_t as TABLE of atelierEx_t


/

¾ Create type Usine_t as object (noU int, villeU varchar2(50),


lesAteliersIn lesAteliersIn_t, lesAteliersEx lesAteliersEx_t) /
Création de la table Usine avec 2 sous-tables (Nested) et Insertion d'objets

¾ Create table Usine of Usine_t


(Constraint pk_Usine Primary Key(noU))
NESTED TABLE lesAteliersIn STORE AS TableLesAteliersIn,
NESTED TABLE lesAteliersEx STORE AS TableLesAteliersEx ;

Insertion d'un objet de Usine:


Insert Into Usine values(usine_t(100, 'Québec',
lesAteliersIn_t (atelierIn_t('456', 'Dion', 'soudure argon'),
atelierIn_t('345', 'Morin', 'coupe laser')),
lesAteliersEx_t ( atelierEx_t('Jean', 'Québec'),
atelierEx_t('Luc', 'Montréal')))) ;
Contrainte sur les attributs de sous-table : ALTER TYPE

¾ Impossible à la création, de poser une contrainte du genre CHECK, NOT


NULL et UNIQUE sur un attribut de la sous-table (imbriquée)!

¾ Il faut le faire avec un Alter Type sur la table physique: TableLesAteliersIn:

Alter Table TableLesAteliersIn ADD Constraint c_tel Check(tel is not null);


Insertion d'un objet dans une collection existante

¾ Insertion d'un atelier externe pour l'usine no 200:

Insert into TABLE(Select u.lesAteliersEx From Usine u


Where u.noU = 200) x
Values (atelierEx_t('Jacques', 'Rimouski'));

¾ Insertion d'un atelier interne à l'usine 200:

Insert into TABLE (Select u.lesAteliersIn From Usine u


Where u.noU = 200) x
Values (atelierEn_t('Julia', 'Beaupré'));
Implantation du lien multiple externe
Implantation OR de l'association 1 -* du Mnav avec lien multiple externe
Le lien multi vers la classe externe Entrainement est matérialisé par une collection
(table imbriquée) de références vers une classe externe (de valeurs).

Pilote
noP* Entrainement
nomP codeE*
gradeP dateE
lesEntrRef regionE

En relationnel NF2: Entrainement ( codeE*, dateE, regionE)


Pilote(noP*, nomP, gradeP, lesEntrRef) (avec attribut de collection de ref)

Create Type entrainement_t as Object (codeE int, dateE Date, regionE int)
/
Lien externe multi (avec table imbriquée de REF)
Mnav: Le lien externe sous-tend le type REF et le multi sous-tend la notion
de collection de REF dont chacune pointe OBLIGATOIREMENT sur un
objet de type entrainement_t. C'est une sous-table de références.
Create Type refEntr_t as Object (refEntr REF entrainement_t) /

Create Type lesEntrRef AS TABLE OF refEntr_t / ou


dans ce cas-ci avec un seul attribut:

Create Type lesEntrRef_t AS TABLE OF REF entrainement_f /

Create Type pilote_t as Object (noP int, nom varchar2(35), grade char(1),
lesEntrRef lesEntrRef_t) /
-- lesEntrRef_t est une structure de collection (ensemble) i.e. une table
imbriquée de références dont la valeur ne peut pas être nulle.
Création des tables Pilote et Entrainement

Create Table Pilote of pilote_t ( Constraint pk_Pilote Primary Key(noP))


NESTED TABLE lesEntrRef STORE AS TableLesEntrRef;

*** La contrainte NOT NULL pour lesEntrRef est effectuée sur la sous-table physique TableLesEntrRef

Create Table of entrainement_t;

Si les références aux objets vers Entrainement doivent exister ( NOT NULL),
il faut modifier le type de l'attribut dans la table physique par le ALTER
TYPE: Table imbriquée stockée
Alter Table tableLesEntrRef ADD Constraint c_RefEntr Check(refEntr is not
null);
NB: il ne peut pas y avoir une contrainte NOT NULL définie lors de la création de la
table hôte.
La collection VARRAY
Collection de type VARRAY

¾ Implémente la structure de collection avec ordonnement des objets. Elle


ne peut pas être elle-même avec une autre imbrication.

¾ Pré-dimensionnée et ordonnée avec indexation d'origine 1: l'allocation de


l'espace dépend du nombre courant d'objets:
Si une collection VARRAY(5) est initialement utilisée pour stocker 3
objets, l'espace physique alloué est limité à celui nécessaire pour stocker
ces 3 premiers objets. D'autres pourront être éventuellement ajoutés et
cela jusqu'à 5.

¾ Avec le type VARRAY, la collection est stockée soit dans l'objet parent,
soit comme un objet opaque soit : RAW ou BLOB

¾ Est extensible jusqu'à l'atteinte de la limite fixée à sa création.


Quand utiliser un VARRAY()

Usages :

1. Lorsque le nombre d'éléments dans la collection est limité et fixé. La taille


max de chaque élément est environ 4000 octets.

2. Nécessité de maintenir un ordre parmi les objets de la collection


VARRAY;

3. Si la mise à jour se fait dans toute la collection de préférence à un objet


de la collection.

4. L'accès par indice est très performant surtout lorsque le VARRAY est de
petite taille et stocké avec les autres attributs du parent (in-line VARRAY).
Structure interne du VARRAY

¾ Pour un VARRAY(3) pour stocker un objet colonne composé de 2


attributs:

Création avec deux objets:

Création avec 3 objets qui sont stockés:

Si le 2ème objet est supprimé : l'espace est noté null et récupérable:

null null
Objet 1 Objet 2 Objet 3

L'ajout d'un objet (bleu) dans le VARRAY ré-utilise l'espace de la 2e place.

Objet ajouté
Association 1 - * : Vue logique du VARRAY

¾ La table (typée ou non) permet d'être l'hôte (parent) logique d'une


collection de type Varray (représentation tabulaire (sous-table)..
Par exemple: La table Chercheur peut avoir une sous-table lesContacts (OC) qui
permet à un chercheur d'avoir un nombre variable, limité et ordonné d'adresses de
Courriel.
Attribut courriel de type courriel_t formant l'objet de colonne Attribut de la table (OC)
Chercheur dont le type est {}

Chercheur: no: int nom:varchar lesContacts:{ } varray dim. 3

courriel : courriel_t

Bois@ibm.com

15 E.F.BOIS EFBois@ny.edu

Bois@home.net

A. Gamache Objet-Relationnel
Collection de taille limitée et prédéterminée : VARRAY()

Courriel : courriel_t

CREATE TYPE courriel_t as Object (courriel varchar2(20)) /

lesContacts:{ }

Courriel: courriel_t

Create Type lesContacts_t AS VARRAY(3) of courriel_t / -- type de la sous-table


Ou
Create or Replace Type lesContacts_t AS VARRAY(3) of varchar2(20) /

Chercheur: no:int nom:varchar lesContacts:{ }


courriel: courriel_t
Table avec le type varray

¾ Création d'une table objet typée incluant un type Varray:

CREATE TYPE chercheur_t as Object (no NUMBER, nom CHAR(20),


lesContacts lesContacts_t, age int) /

Create Table Chercheur of chercheur_t;

¾ Création d'une table non typée relationnelle incluant un varray:

Create Table Chercheur (no NUMBER, nom CHAR(20),


lesContacts lesContacts_t)
Modification du type des éléments du VARRAY

¾ Il est possible de modifier le type des éléments du VARRAY:

‰ ALTER Type lesContacts_t MODIFY ELEMENT TYPE varchar2(15)


CASCADE [Not Including Table Data] ;

¾ Modification possible de la taille du VARRAY: de 3 à 10

‰ ALTER Type lesContacts MODIFY LIMIT (10) CASCADE [Not


Including Table Data] ;
TEST d'inclusion dans une collection : MEMBER OF

Select
From lesContacts
Where contact_t ('345-346) MEMBER OF lesContacts;
Tables du dictionnaire pour les collections VARRAY

¾ USER_COLL_TYPES : fournit le nom de la collection, la limite sup, ..

Select type_Name, coll_Type, upper_Bound, elem_Type_Name


From USER_COLL_TYPES;

¾ USER_TYPE _ATTRS: fournit le nom et le type des colonnes d'une


collection (Nested Table ou VARRAY)

Select ATTR_NAME, TYPE_NAME, LENGTH


From USER_TYPE_ATTRS;
Restrictions avec le VARRAY

¾ Impossible de définir un index sur un attribut du VARRAY


Create index courriel_idx on courriel; -- interdit

¾ Impossible de définir les contraintes CHECK(), NOT NULL*, UNIQUE sur


un attribut (colonne) d'une collection VARRAY.

• Une contrainte NOT NULL peut être ajoutée seulement avec le ALTER
TABLE:

ALTER TABLE Chercheur ADD CONSTRAINT lesContactsNotNull


Check( lesContacts IS NOT NULL) CASCADE [Not Including Table Data] ;
Suite… Création de la table avec le type VARRAY

Chercheur: no nom lesContacts: { }

Courriel:courriel_t 1 Objet colonne


1 Objet de table

Bois@ibm.com

15 E.F.Bois EFBois@ny.edu

Bois@home.net

engel@ulaval.ca

20 Engel
robertEngel@sympatico.ca
Supprimer tous les objets de chercheur:
DELETE Chercheur;
Manipulation des objets du VARRAY

¾ Ajout d'un chercheur avec 2 adresses de courriel

Insert into Chercheur Values (chercheur_t( 37, 'Demers',


lesContacts_t(courriel_t ('Pasteur@.CHU.com'),
courriel_t('LP@HopitalNord.com')))) ;

SQL> select * from chercheur; -- 1 objet chercheur avec 1 objet colonne


- - composé de deux éléments.

NO NOM LESCONTACTS
37 Demers LESCONTACTS_T(COURRIEL_T('Pasteur@.CHU.com '),
COURRIEL_T('LP@hopitalNord.com '))
Suppression des objets et lecture des objets du VARRAY

¾ Delete Chercheur ; -- supprime tous les objets de la table objet Chercheur y


compris les objets-colonnes.

¾ Accès aux éléments du VARRAY :

1. Impossible avec le DML (Insert, Update, Delete) comme c'est le cas avec
la Nested Table de mettre à jour par exemple le Varray avec SQL. Le
select est permis.

2. Les opérations de mise à jour sont à faire en PL/SQL en utilisant une


variable déclarée avec le type du VARRAY (tableau) et de faire les
modifications dans ce tableau et ensuite faire un UPDATE .
Ajout d'un objet comportant des éléments de Varray

Chercheur: no nom lesContacts: { }

Courriel:courriel_t

Bois@ibm.com

15 E.F.Bois EFBois@ny.edu

20 Engel engel@ulaval.ca
Ajout d'un objet Chercheur:
Insert into Chercheur values (
chercheur_t(20, 'Engel', lesContacts_t(courriel_t('engel@ulaval.ca'))));

L'ajout d'un 2è contact au chercheur no 20: impossible avec insert dans un Varray.

Ajout d'un chercheur avec 2 contacts nuls (mise à jour subséquente possible):
Insert into Chercheur values (
Chercheur_t(50, 'Brassard', lesContacts_t(courriel_t(NULL), contact_t(NULL), ));
Modification d'un VARRAY() avec PL/SQL

Declare
tableauLesContacts lesContacts_t;
Begin
Select lesContacts INTO tableauLesContacts From Chercheur c
Where c.no = 15 FOR UPDATE OF lesContacts; -- init du tableau
-- modification du 2è et 3è objet-colonne du tableau
tableauLesContacts(2) := courriel_t ('Robert E. Engel@ulaval.ca');
tableauLesContacts(3) := courriel_t ('R. E. Engel@ulaval.ca');
UPDATE Chercheur c
SET c.lesContacts = tableauLesContacts Where c.noC = 15 ;
End;
/
Le FOR UPDATE verrouille l'objet du chercheur no 15, le temps de la mise à jour. Il est
déverrrouillé par un commit;
Affichage de la collection lesContacts avec la directive TABLE()

Select p.contact
From Table(Select c.lesContacts From Chercheur c Where c.no =20) p ;

3 Objets sont affichés:

courriel_t('Robert E@ulaval.ca');
courriel_t('R. E. Engel@ulaval.ca');
courriel_t('Engel@ulaval.ca'))));

S-ar putea să vă placă și