Selon ma compréhension de vos spécifications, votre environnement commercial implique une relation ternaire au niveau conceptuel . À cet égard, vous devez définir:
- le type de relation (ou d' association ) entre les types d'entité Personne et Enquête ;
- le type de relation entre l' enquête et la question ;
- le type de relation qui établit le lien entre les deux types de relation susmentionnés et, par conséquent, entre la personne , l' enquête et la question , c'est-à-dire la réponse (un nom plus court qui simplifie l'interprétation, de mon point de vue).
Donc, je considère que vous êtes sur la bonne voie avec votre approche 1 , même si elle nécessite quelques petits raffinements (pourtant importants) pour la rendre plus précise. Je détaillerai ces améliorations et d'autres considérations pertinentes dans les sections suivantes.
Règles métier
Développons un peu les règles métier applicables et reformulons-les de la manière suivante:
- Une personne s'inscrit à zéro-un ou plusieurs sondages
- Une enquête obtient l'enregistrement de zéro ou une personne
- Une enquête est intégrée par un-à-plusieurs questions
- Une question intègre zéro-un-ou-plusieurs sondages
- Une question reçoit zéro ou une ou plusieurs réponses
- Une réponse est fournie par une seule personne dans le contexte d'une seule enquête
Diagramme expositoire IDEF1X
Ensuite, j'ai créé l'IDEF1X, un diagramme présenté dans la figure 1 , qui synthétise les règles métier formulées ci-dessus:
Une définition d'intégration pour la modélisation de l'information ( IDEF1X ) est une technique de modélisation hautement recommandable qui a été établie en tant que norme en décembre 1993 par le National Institute of Standards and Technology ( NIST )des États-Unis. Il est solidement basé sur des travaux théoriques rédigés par le seul fondateur du modèle relationnel , c'est-à-dire le Dr EF Codd, ainsi que sur la vision des relations d'entité développée par le Dr PP Chen .
La relation PersonSurvey
À mon avis, la relation PersonSurvey doit fournir un moyen d'autorisation pour qu'une personne puisse participer à une enquête donnée . De cette façon, une fois qu'une certaine personne a été inscrite à un sondage spécifique , elle est autorisée à fournir des réponses aux questions qui intègrent le sondage respectif .
La relation SurveyQuestion
Je suppose que la propriété (ou attribut) appelée suvery_question.question_number dans votre diagramme est utilisée pour représenter l' ordre de présentation d'une instance de question donnée par rapport à une enquête particulière . Comme vous pouvez le voir, j'ai désigné une propriété telle que SurveyQuestion.PresentationOrder , et je pense que vous devriez empêcher que (i) deux ou plusieurs valeurs Question.QuestionNumber partagent (ii) la même valeur PresentationOrder dans (iii) la même occurrence SurveyQuestion .
Pour représenter ce besoin, j'ai inclus une clé ALTERNATE composite (AK) dans la boîte représentant ce type d'entité, qui comprend la combinaison de propriétés ( SurveyNumber, QuestionNumber, PresentationOrder ). Comme vous le savez bien, un AK composite peut être déclaré dans une conception DDL logique à l'aide d'une contrainte UNIQUE à plusieurs colonnes (comme je l'ai illustré dans le SurveyQuestion
tableau qui fait partie de la disposition DDL expositoire exposée quelques sections ci-dessous).
Le type d'entité Response
Oui, avec le type d'entité Response , je représente une relation entre deux autres relations ; cela peut sembler gênant à première vue, mais il n'y a rien de mal à cette approche, tant qu'elle (a) représente avec précision les caractéristiques du contexte commercial d'intérêt et (b) est correctement représentée dans une disposition de niveau logique.
Oui, vous avez tout à fait raison, ce serait une erreur de représenter cette partie du scénario au niveau logique de l'abstraction au moyen de deux Response.SurveyNumber
(ou, disons Response.SurveyId
) valeurs référencées à partir de deux colonnes différentes dans la même Response
ligne.
Disposition logique SQL-DDL dérivée
-- You should determine which are the most fitting
-- data types and sizes for all your table columns
-- depending on your business context characteristics.
-- As one would expect, you are free to make use of
-- your preferred (or required) naming conventions.
CREATE TABLE Person (
PersonId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
GenderCode CHAR(3) NOT NULL,
BirthDate DATE NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Person_PK PRIMARY KEY (PersonId),
CONSTRAINT Person_AK UNIQUE (
FirstName,
LastName,
GenderCode,
BirthDate
)
);
CREATE TABLE Survey (
SurveyNumber INT NOT NULL,
Description CHAR(255) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Survey_PK PRIMARY KEY (SurveyNumber),
CONSTRAINT Survey_AK UNIQUE (Description)
);
CREATE TABLE PersonSurvey (
PersonId INT NOT NULL,
SurveyNumber INT NOT NULL,
RegisteredDateTime DATETIME NOT NULL,
--
CONSTRAINT PersonSurvey_PK PRIMARY KEY (PersonId, SurveyNumber),
CONSTRAINT PersonSurveyToPerson_FK FOREIGN KEY (PersonId)
REFERENCES Person (PersonId),
CONSTRAINT PersonSurveyToSurvey_FK FOREIGN KEY (SurveyNumber)
REFERENCES Survey (SurveyNumber)
);
CREATE TABLE Question (
QuestionNumber INT NOT NULL,
Wording CHAR(255) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Question_PK PRIMARY KEY (QuestionNumber),
CONSTRAINT Question_AK UNIQUE (Wording)
);
CREATE TABLE SurveyQuestion (
SurveyNumber INT NOT NULL,
QuestionNumber INT NOT NULL,
PresentationOrder TINYINT NOT NULL,
IsMandatory BIT NOT NULL,
IntegratedDateTime DATETIME NOT NULL,
--
CONSTRAINT SurveyQuestion_PK PRIMARY KEY (SurveyNumber, QuestionNumber),
CONSTRAINT SurveyQuestion_AK UNIQUE (
QuestionNumber,
SurveyNumber,
PresentationOrder
),
CONSTRAINT SurveyQuestionToSurvey_FK FOREIGN KEY (SurveyNumber)
REFERENCES Survey (SurveyNumber),
CONSTRAINT SurveyQuestionToQuestion_FK FOREIGN KEY (QuestionNumber)
REFERENCES Question (QuestionNumber)
);
CREATE TABLE Response (
SurveyNumber INT NOT NULL,
QuestionNumber INT NOT NULL,
PersonId INT NOT NULL,
Content TEXT NOT NULL,
ProvidedDateTime DATETIME NOT NULL,
--
CONSTRAINT Response_PK PRIMARY KEY (SurveyNumber, QuestionNumber, PersonId),
CONSTRAINT ResponseToPersonSurvey_FK FOREIGN KEY (PersonId, SurveyNumber)
REFERENCES PersonSurvey (PersonId, SurveyNumber),
CONSTRAINT ResponseToSurveyQuestion_FK FOREIGN KEY (SurveyNumber, QuestionNumber)
REFERENCES SurveyQuestion (SurveyNumber, QuestionNumber)
);
Deux clés étrangères composites dans le Response
tableau
C’est probablement le point le plus important à discuter: les références faites à partir d’une Response
ligne
SurveyQuestion.SurveyNumber
, et
SurveyPerson.SurveyNumber
doit avoir des valeurs correspondantes . En ce qui me concerne, la meilleure option pour appliquer cette condition de manière déclarative est d'utiliser deux clés étrangères composites (FK).
Comme le montre la conception DDL, le premier FK fait référence à la PersonSurvey
table KEY PRIMARY (PK), c'est-à-dire (PersonId, SurveyNumber)
, et est conforme aux colonnes Response.PersonId
et Response.SurveyNumber
.
Le second FK pointe vers la SurveyQuestion
table PK, c'est-à-dire (SurveyNumber, QuestionNumber)
, et est, par conséquent, composé des colonnes Response.SurveyNumber
et Response.QuestionNumber
.
De cette façon, la Response.SurveyNumber
colonne est assez instrumentale car elle est utilisée dans le cadre d'une référence FK dans deux contraintes différentes.
Avec cette méthode, on assure garantie système de gestion de base de données l' intégrité référentielle de
- a)
Response
au PersonSurvey
;
- b)
Response
au SurveyQuestion
; et
- (c) chacune des tables représentant un type d'entité associative aux tables représentant des types d'entité indépendants, à savoir
Person
, Survey
et Question
.
Données dérivées pour éviter les anomalies de mise à jour
J'ai remarqué dans votre diagramme deux éléments qui, selon moi, méritent d'être mentionnés. Ces éléments sont liés à deux PersonSurvey
colonnes qui peuvent (devraient) être dérivées .
À cet égard, vous pouvez déduire la PersonSurvey.IsStarted
donnée par l' interrogation si une donnée Person
événement a fourni un ou plusieurs Responses
à Questions
qui intègrent une exacte Survey
via la SurveyQuestion
table.
Et vous pouvez également obtenir le PersonSurvey.IsCompleted
point de données en déterminant si une Person
instance donnée a fourni un Response
à tous ceux Questions
qui co-contiennent une valeur de «VRAI» dans la IsMandatory
colonne d'une SurveyQuestion
ligne spécifique .
En dérivant ces valeurs, vous évitez certaines anomalies de mise à jour qui se seraient éventuellement produites si vous aviez conservé ces valeurs dans la SurveyQuestion
colonne.
Considération importante
Comme @Dave le fait remarquer à juste titre dans son commentaire, si vous êtes confronté à une exigence future exigeant la gestion de différents types de réponses impliquant la gestion des dates, des valeurs numériques, des choix multiples et d'autres aspects possibles, vous devrez étendre cette disposition de base de données.
ID
etNumber
, mais sinon, c'est fantastique. Je vous remercie.C'est une des raisons pour lesquelles je n'aime pas préfixer les colonnes lors de leur migration en tant que clés étrangères. Dans votre premier cas, l'outil de modélisation peut vous obliger à préfixer l'une des
survey_id
colonnes dusurvey_person_question_response
tableau. Vous pourrez peut-être ajuster cela une fois la relation établie.Si nécessaire, supprimez le champ ID d'enquête redondant lorsque vous créez le modèle physique là où vous n'avez pas besoin de la colonne dupliquée. Comme vous l'avez identifié, vos deux modèles ont des problèmes, mais je pense que le premier modèle est globalement meilleur.
la source