OVH Cloud OVH Cloud

Est il conseillé de mettre des contraintes FOREIGN KEY ?

11 réponses
Avatar
Gilles TOURREAU
Salut tout le monde !

J'ai une base de donnée qui est utilisé par un programme réalisé en
.NET. La suppression et modification en cascade est donc réalisé
automatiquement par la partie application (avec les DataSet du .NET
Framework)...

Est-il conseillé de mettre une contrainte de clé étragère avec des NO
ACTION pour la modification/suppression ? Si oui pourquoi ?
Du style :

ADD CONSTRAINT MaContrainte FOREIGN KEY (CléEnfant) REFERENCES Parent
(CléParent) ON DELETE NO ACTION ON UPDATE NO ACTION

En vous remerciant par avance de vos lumières...

Cordialement

--
Gilles TOURREAU
Responsable informatique
gilles.tourreau@pos.fr

Société P.O.S
Spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr

1 réponse

1 2
Avatar
oroc
Gilles TOURREAU avait soumis l'idée :
SQLpro [MVP] a présenté l'énoncé suivant :
Gilles TOURREAU a écrit :
[...]

Je vous remercie de vos réponses...

Mais ma question était faut-il comme même mettre des contraintes
d'intégrité avec aucune action (NO ACTION).




je pense que vous vous méprenez sur le sens du NO ACTION qui est en fait un
quasi synonyme de RESTRICT.

Démonstration :

CREATE TABLE T_MERE
(CLE_MER INT NOT NULL PRIMARY KEY)

CREATE TABLE T_FILLE
(CLE_FIL INT NOT NULL PRIMARY KEY,
CLE_MER INT FOREIGN KEY REFERENCES T_MERE (CLE_MER) ON UPDATE NO ACTION
ON DELETE NO ACTION)

INSERT INTO T_MERE VALUES (1)
INSERT INTO T_MERE VALUES (2)
INSERT INTO T_MERE VALUES (3)

INSERT INTO T_FILLE VALUES (100, 1)
INSERT INTO T_FILLE VALUES (101, 7)

--=> Serveur : Msg 547, Niveau 16, État 1, Ligne 1
--=> Conflit entre l'instruction INSERT et la contrainte COLUMN FOREIGN KEY
'FK__T_FILLE__CLE_MER__00551192'. Le conflit est survenu dans la base de
données 'test', table 'T_MERE', column 'CLE_MER'.
--=> L'instruction a été arrêtée.

DELETE FROM T_MERE
WHERE CLE_MER = 1

--=> Serveur : Msg 547, Niveau 16, État 1, Ligne 1
--=> Conflit entre l'instruction DELETE et la contrainte COLUMN REFERENCE
'FK__T_FILLE__CLE_MER__00551192'. Le conflit est survenu dans la base de
données 'test', table 'T_FILLE', column 'CLE_MER'.
--=> L'instruction a été arrêtée.

UPDATE T_MERE
SET CLE_MER = 9
WHERE CLE_MER = 1

--=> Serveur : Msg 547, Niveau 16, État 1, Ligne 1
--=> Conflit entre l'instruction UPDATE et la contrainte COLUMN REFERENCE
'FK__T_FILLE__CLE_MER__00551192'. Le conflit est survenu dans la base de
données 'test', table 'T_FILLE', column 'CLE_MER'.
--=> L'instruction a été arrêtée.

Comme vous pouvez le constater NO ACTION a bien entrainé systématiquement
un viol de contrainte comme l'aurait fait RESTRICT.

En fait la différence est TRES subtile : RESTRICT est une contrainte
déferrable et NO ACTION interdit la défarrabilité.
Comme cette notion n'est pas gérée dans SQL Server, l'effet est le même.

Dans d'autres SGBR, comme Oracle, DB2 ou PostGreSQL en fonction de la façon
dont est géré la déférabilité de la contrainte, le RESTRICT permettra
d'inserer la ligne même s'il y a violation de clef, à condition que ce viol
de clef soit temporaire et que la situation devienne finalement cohérente
avant la fin de la transaction.
Autrement dit en RESTRICT avec déférabilité et dans le cadre d'une
transaction, je peut insérer une commande faisant référence à un client
inexistant, puis ajouter ce nouveau client et le commit vérifiera la
contrainte au finish et non à priori (c'est à dire à l'insertion de la
ligne) comme il l'aurait fait pour du NO ACTION.

Si vous voulez de plus amples informations sur les notions de déérabilité
des contraintes, je vous invite à lire mon bouqui sur SQL qui en parle de
façon détaillé.

http://sqlpro.developpez.com/booksql05/

A +



Du style :

ADD CONSTRAINT MaContrainte FOREIGN KEY (CléEnfant) REFERENCES Parent
(CléParent) ON DELETE NO ACTION ON UPDATE NO ACTION

C'est à dire quand on supprime/modifie un enregistrement dans une table
aucune autre action n'est réalisé... (Tout est fait au niveau de
l'applicatif .NET)...

Cordialement






Voilà qui est plus clair...

Je vous remercie de vos explications.

Cordialement



Bonjour,

Le monde réel est plus facile à représenter avec des objets.
Hors, dans le monde relationnel, on ne peut représenter que des tables.
Donc pour représenter un objet en relationnel, on peut être ammené
à utiliser plusieurs tables, mais qui sont liés entre elles lors des
opérations de mise à jour ou de suppression

Si je dois représenter un objet commande en relationnel, je dois
utiliser 2 tables
- Une ligne pour l'entête dans la table "commandes" :
(N°Cmde, Date, Adresse, etc..)
- des lignes de commandes dans la tables "details commandes"
(N°Cmde, N° Pdt, Qte,Prix Date, Adresse, etc..)

Dans ce cas il y a bien un clé étrangère en DELETE CASCADE entre
la table "Commandes" et "Details Commandes".
Si je supprime l'entête de commande, cela supprime automatiquement les
details associés

A L'inverse, il y a aussi un clé étrangère entre la table "Produit" et
la table "Details Commandes".
Mais ici, la clé étrangère "DOIT ETRE" NO_ACTION. Car je veux empêcher
la suppression d'un produit du catalogue si il estr déjà commandé.

Voilou !
1 2