Relation réflexive avec mise à jour/suppression en cascade
Bonsoir,
aujourd'hui, j'ai eu envie de mettre à l'épreuve mon SGBD : lui serait-il possible de gérer la mise à jour/suppression en cascade dans le cadre d'une relation réflexive ? Je m'explique :
Soit la table test constituée de 2 champs, pk et fk :
Code:
1 2 3 4 5 6
|
pk fk
-----
1 1
2 1
3 2 |
Je souhaite établir une relation entre le champ fk (clef étrangère) et le champ pk (clef primaire) afin que la suppression/mise à jour d'un enregistrement entraîne la suppression/mise à jour des enregistrements enfants.
En l'occurrence, la suppression de l'enregistrement 1/1 entraînerait donc celle de l'enregistrement 2/1... qui entraînerait elle-même celle de l'enregistrement 3/2.
Le but n'est pas de gérer cela avec un trigger, mais de savoir si le SGBD est en mesure de le gérer dans le cadre d'une simple relation avec cascade.
J'ai donc tenté d'exécuter l'instruction de création de table suivante sous SQL Server 2000 :
Code:
1 2 3 4 5 6
|
CREATE TABLE test (
pk NUMERIC,
fk NUMERIC,
CONSTRAINT c1 PRIMARY KEY (pk),
CONSTRAINT c2 FOREIGN KEY (fk) REFERENCES test (pk) ON UPDATE CASCADE ON DELETE CASCADE); |
Et SQL Server 2000 de me répondre :
Citation:
L'introduction d'une contrainte de clé étrangère 'c2' dans la table 'TEST' peut provoquer des cycles ou des accès en cascade multiples. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION ou modifiez les autres contraintes de clés étrangères
La réponse n'est pas celle que j'espérais, mais elle a le mérite d'être claire.
Me demandant si un autre SGBD serait en mesure de gérer ce type de relation, j'ai essayé de la mettre en place sous Access. Access me laisse bien mettre en place la relation, mais lorsque j'essaie de supprimer un enregistrement parent, j'essuie le refus suivant :
Citation:
Impossible de mettre à jour; actuellement verrouillé(e).
Faut-il en déduire qu'il est impossible à un SGBD de gérer nativement (sans trigger) une mise à jour/suppression en cascade dans le cadre d'une relation réflexive ?
Remarques :
- une KB de Microsoft décrit le message d'erreur SQL Server que j'ai cité plus haut. A noter que la KB s'attarde plus sur la question des "accès en cascade multiples" que sur celle des "cycles", sujet de la présente discussion.
WITH - Jointure récursive
Bonjour,
Citation:
Envoyé par J1
je ne connaissais pas la clause WITH. Je me garderai donc bien de la ranger d'emblée dans telle ou telle catégorie. Où la situerais-tu pour ta part ?
Hum... La structure de WITH est la suivante :
http://www.fsmwarden.com/developpez/...lin(BNF)30.jpg
Si donc on admet qu’une requête (Query) est déclarative, la clause WITH est du genre déclaratif.
N.B. En réponse à votre remarque, sur le forum, j'ai pris l'habitude du "vous".
Citation:
Envoyé par J1
Au fait, est-elle largement implémentée dans le petit monde des SGBD ?
Je dois vous avouer que je n'en sais rien. La clause WITH est définie dans le cadre de la norme SQL, à laquelle sont conformes SQL Server et DB2. Concernant Oracle, la jointure récursive est disponible, mais sous une forme différente, avec une performance au demeurant excellente (par exemple, 100 millisecondes pour extraire une nomenclature, dans une table de 500000 lignes, dans un secteur où l’on ne rigole pas avec les nomenclatures, à savoir celui de la grande distribution).
Styles utilisés pour effectuer une jointure récursive (requêtes non testées) :
Soit la table I (Composant, Composé)
Pour obtenir les composants du composé "xyz" :
Selon la norme SQL (à faire valider par SQLpro) :
Code:
1 2 3 4 5 6
| With V (Composant)
As (Select Composant From I Where Composé = "xyz"
UNION ALL
Select I.Composant From V, I
Where I.Composé = V.Composant)
Select Composant From V ; |
Avec Oracle :
Code:
1 2 3
| Select Composant
From I ...
Start With Composé = "xyz" Connect By Prior Composant = Composé |
Hors SQL, en relationnel pur (avec le langage Tutorial D) :
Code:
TCLOSE (I {Composé, Composant}) WHERE Composé = "xyz") {Composant}