MySQL : contrainte circulaire.

Répondre
LupusMic
le 12/08/2007 à 08:17
LupusMic
Bonjour tout le monde,

J'ai créé les tables suivantes (j'élude volontairement les attributs qui ne sont pas pertinent ici :

cre.sql
create table accounts
( id integer auto_increment
, people_id integer default null
, username varchar(255) unique not null
, foreign key (people_id) references peoples(id)
, primary key (id)
) type='innodb' ;

create table peoples
( id integer auto_increment
, creator_account_id integer not null
, foreign key (creator_account_id) references accounts(id)
, primary key (id)
) type='innodb' ;


Le principe est le suivant. Sur le site, on créé un compte (table accounts) pour pouvoir se loguer. Lors de l'inscription, un compte est créé ainsi qu'un profil (table peoples). Un compte ne correspond pas forcément à un profil (par exemple, les comptes god et admin ne sont pas des personnes), mais un profil est forcément créé par un compte.

Comme je m'en doutais lorsque j'ai écris ces tables, on a droit à un joli deadlock lorsqu'on veut supprimer un compte.

Est-ce que c'est le genre de cas où la table de jointure est obligatoire ? Et est-ce que mes tables sont mal analysées, ou est-ce une limitation du modèle des contraintes SQL ?

Merci de vos réflexions !
Développeur récurrent, procédural et relationnel. Caustique soupe-au-lait.
mojorisin
le 12/08/2007 à 12:50
mojorisin
Tu auras des problemes également à l'insertion avec ce schema.
Avec mysql qui n'implemente partiellement la gestion de clé étrangère ce n'est pas évident.
Il faut voir si mysql gère les contraintes déférables :

CONSTRAINT fk_people_account FOREIGN KEY (creator_account_id) REFERENCE accounts (id) DEFERRABLE

Au demarage de la session tu fais un :
SET CONSTRAINTS fk_people_account DEFERRED

Ensuite tu lances une transaction :
Insertion dans accounts
Insertion dans peoples
update de accounts pour définir la clé étrangère
commit

Remise en place de la contrainte :
SET CONSTRAINTS fk_people_account IMMEDIAT

Je n'ai pas testé cela avec mysql et je n'ai pas regarder la doc pour savoir les types de contraintes que peut gerer mysql.
Mais j'ai des doutes, le système relationnel de mysql est loin d'etre complet
echo ’16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D4D465452snlbxq’|dc
mojorisin
le 12/08/2007 à 12:56
mojorisin
Bon je viens de regarder vite fait, il semble que mysql ne prenne pas en compte DEFERRABLE.
Tu n'auras d'autre choix alors que de désactiver la vérification d'integrité :
SET FOREIGN_KEY_CHECKS = 0;
// requetes ici
SET FOREIGN_KEY_CHECKS = 1;
echo ’16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D4D465452snlbxq’|dc
LupusMic
le 13/08/2007 à 11:34
LupusMic
(Koboneil) Pourquoi n'y ais-je pas pensé plus tôt ? Ton intervention m'avance beaucoup.

Lorsque je fais quelque chose, je ne le fais pas pour rien. Si tu veux m'aider, relis mon explication. people_id est là pour référencer le People associé au compte utilisateur.

(mojorisin) Merci pour ta réponse constructive. Ben en fait, les insertions se passent très bien, puisque la clé étrangère people_id peut être nulle (puisqu'à un compte n'est pas forcément associé un people). Mais c'est la suppression, qui même lorsque je faisais un delete sur plusieurs tables me bloquait.

Merci pour l'astuce de la désactivation des contraintes.

Cependant, je pense que je vais utiliser une table de jointure :

cre.sql
create table profiles
( account_id integer not null
, people_id integer not null

, primary key (account_id,people_id)
, foreign key (account_id) references accounts(id)
, foreign key (people_id) references peoples(id)
) type='innodb' ;


Ça m'éviteras les problèmes ;) Même si ça me plait moins (ça me parait goret en fait).

Merci en tout cas !
Développeur récurrent, procédural et relationnel. Caustique soupe-au-lait.
Répondre

Ecrire un message

Votre message vient d'être créé avec succès.
LoadingChargement en cours