Comment concevoir cette base de données pour éviter la dépendance cyclique?

12

Il existe deux tableaux:

  1. Utilisateur
  2. Adresse

L'utilisateur contient une référence à l'adresse.

L'adresse contient les colonnes CreatedBy et ModifiedBy, qui fait référence à l'utilisateur.

Comment concevoir cette base de données pour éviter une dépendance cyclique?

Shashi
la source
4
Êtes-vous sûr que ModifiedBy n'est pas une référence à l'utilisateur de la base de données qui a effectué la modification, plutôt qu'à l'utilisateur des applications (qui résiderait dans la table User)? Quoi qu'il en soit, cela n'a pas vraiment d'importance. Je ne vois pas pourquoi il y a un vrai problème?
Philᵀᴹ
Lequel sera créé en premier. Comme CreatedBy ANd Modifiedby est une donnée incontournable. Et la table utilisateur ne devrait pas avoir addressid comme null .. Problème de poulet-oeuf. Comme je résous cela en créant une nouvelle table UserAddress qui contient la référence pour userid et addressid
Shashi
2
Vous pouvez toujours utiliser des contraintes différées si votre SGBD les prend en charge.
Colin 't Hart
NB Le modèle relationnel prend en charge deux insertions ou mises à jour en une seule opération atomique, c'est vraiment dommage que cela ne soit pas pris en charge en SQL (car les contraintes différées - même si je les ai suggérées - sont assez horribles).
Colin 't Hart

Réponses:

7

Au lieu de rechercher des trucs et astuces (contraintes différées incluses), je vous suggère de concevoir simplement votre moyen de sortir de ce "verrou de référence" - alors essayez quelque chose comme ceci:


Les faits

  • L'utilisateur(UserID) existe.
  • L'adresse a(AddressID) été créée par l' utilisateur(UserID) .
  • L'adresse a(AddressID) été créée le Date(DateCreated) .
  • L'adresse a(AddressID) été modifiée pour la dernière fois par l' utilisateur(UserID) à la date(ModifiedOn) .
  • L'utilisateur(UserID) réside à l' adresse(AddressID) depuis la date(ValidFrom) .

Contraintes

  • Each L'adresse a été créée par l' exactly one utilisateur . It is possible that more than one L'adresse a été créée par l' the same utilisateur .

  • Each L'adresse a été créée le exactly one Date . It is possible that more than one L'adresse a été créée le the same Date .

  • For each and Date de l' adresse , l' that adresse a été modifiée par l' at most one utilisateur à la that date .

  • For each and Date de l' utilisateur , l' that utilisateur réside l' at most one adresse depuis la that date .


Logique

entrez la description de l'image ici


En ce qui concerne l'adresse obligatoire, vérifiez cela sur la couche application et encapsulez les instructions de chargement dans une transaction - de cette façon, vous obtiendrez tout ou rien.

Damir Sudarevic
la source
5

Vous n'avez pas d'autre choix que de créer la dépendance cyclique en 2 opérations comme ci-dessous car une table n'existe pas lorsque vous créez la première.

CREATE TABLE A (A_ID INT PRIMARY KEY, B_FK INT);
CREATE TABLE B (B_ID INT PRIMARY KEY, A_FK INT REFERENCES A(A_ID));

ALTER TABLE A ADD B_FK INT;

Si vous souhaitez éviter la dépendance cyclique. Ensuite, vous devez supprimer une contrainte REFERENCES ou vous pouvez ajouter une référence DELETE et UPDATE CASCADE dans un sens. Vous pouvez également implémenter un TRIGGER si votre logique est quelque peu complexe.

PollusB
la source
1
La suppression des contraintes supprime la dépendance cyclique de la définition, mais pas de la conception. Vous pouvez ajouter une table d'événements pour enregistrer le UserID et le AddressID qui ont créé ou modifié la dernière adresse, mais qui déplacent simplement la dépendance un peu plus loin. Dans l'autre sens, si la table User avait des colonnes CreatedBy et ModifiedBy, la dépendance cyclique existerait dans une table. Ceci est similaire à une table d'employés avec une colonne superviseur où le superviseur est également un employé. Comme Phil l'a indiqué - Pas de problème.
Leigh Riffel
@LeighRiffel je suis d'accord. Mais la table d'événements que vous proposez supprime en fait toutes les dépendances cycliques.
ypercubeᵀᴹ
@ypercube En effet, c'est le cas; Je ne sais pas comment j'ai réussi à couper ce fil. Pour être clair, vous ne devriez probablement pas créer une table d'événements même si elle supprime la dépendance cyclique.
Leigh Riffel
Quoi qu'il en soit, je ne pense pas que cette réponse résout le problème. La question (je pense) est de savoir comment éviter le chemin cyclique du tout, pas comment créer les FK avec le chemin cyclique en premier lieu.
ypercubeᵀᴹ