Согласно моему пониманию ваших спецификаций, ваша бизнес-среда подразумевает троичные отношения на концептуальном уровне . В связи с этим необходимо определить:
- тип связи (или ассоциации ) между типами сущностей Person и Survey ;
- тип отношений между опросом и вопросом ;
- тип отношений, который устанавливает связь между двумя вышеупомянутыми типами отношений и, как следствие, между человеком , опросом и вопросом , т. е. ответ (более короткое имя, которое упрощает интерпретацию, с моей точки зрения).
Итак, я считаю, что вы находитесь на правильном пути с вашим подходом 1 , хотя он требует некоторых небольших (но важных) уточнений, чтобы сделать его более точным. Я подробно опишу такие уточнения и другие соответствующие соображения в следующих разделах.
Бизнес правила
Давайте немного расширим применимые бизнес-правила и переформулируем их следующим образом:
- Person регистров в нуль один или-многих обследований
- Survey получает регистрацию нулевой один или-многих людей
- Survey интегрируется один-ко-многим вопросам
- Вопрос интегрирует нулевой один или многим Surveys
- Вопрос получает нуль-один или многих ответов
- Ответ обеспечивается точно-один Человек в контексте точно один год обследования
Описательная схема IDEF1X
Затем я создал IDEF1x на схему , что представлено на рисунке 1 , который синтезирует бизнес - правила , сформулированные выше:
Определение интеграции для информационного моделирования ( IDEF1X ) является весьма рекомендуется метод моделированиякоторый был созданкачестве стандарта в декабре 1993 года Национальным институтом Соединенных Штатов стандартов и технологий ( NIST ). Она прочно основана на теоретическую работе авторства единственным учредителем в реляционной модели , т.е. д - р Ф. Кодда , а также на взгляде сущности-связи , разработанный д - ром П. Чен .
PersonSurvey отношения
На мой взгляд, отношения PersonSurvey необходимы для предоставления средств авторизации, чтобы человек мог принять участие в данном опросе . Таким образом, после того, как определенное лицо было зарегистрировано в определенном опросе , он или она уполномочивается предоставлять ответы на вопросы, которые включают соответствующий опрос .
SurveyQuestion отношения
Я предполагаю, что свойство (или атрибут), называемое suvery_question.question_number в вашей диаграмме, используется для представления порядка представления данного экземпляра Вопроса в отношении конкретного опроса . Как вы можете видеть, я обозначил такое свойство как SurveyQuestion.PresentationOrder , и я думаю, что вы должны предотвратить, чтобы (i) два или более значения Question.QuestionNumber разделяли (ii) одно и то же значение PresentationOrder в (iii) одно и то же вхождение SurveyQuestion .
Чтобы изобразить эту потребность, я включил составной ALTERNATE KEY (AK) в поле, представляющее этот тип сущности, который состоит из комбинации свойств ( SurveyNumber, QuestionNumber, PresentationOrder ). Как вам хорошо известно, составной AK может быть объявлен в логической структуре DDL с помощью ограничения UNIQUE, состоящего из нескольких столбцов (как я показал в SurveyQuestion
таблице, которая является частью описательной схемы DDL, изложенной в нескольких разделах ниже).
Тип объекта ответа
Да, с типом объекта Ответ я изображаю отношения между двумя другими отношениями ; На первый взгляд это может показаться неловким, но в этом подходе нет ничего плохого, если он (а) точно представляет особенности интересующего бизнес-контекста и (б) правильно представлен в макете логического уровня.
Да, вы абсолютно правы, было бы ошибкой изображать эту часть сценария на логическом уровне абстракции с помощью двух Response.SurveyNumber
(или, скажем, Response.SurveyId
) значений, на которые ссылаются два разных столбца в одной Response
строке.
Производная логическая структура SQL-DDL
-- 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)
);
Два составных ИНОСТРАННЫХ КЛЮЧА в Response
таблице
Это, пожалуй, самый важный момент для обсуждения: ссылки на данную Response
строку
SurveyQuestion.SurveyNumber
, и
SurveyPerson.SurveyNumber
должны иметь совпадающие значения . Насколько мне известно, лучший вариант для принудительного применения этого условия декларативным способом - использование двух составных FOREIGN KEY (FK).
Как показано в дизайне DDL, первый FK делает ссылку на PersonSurvey
таблицу PRIMARY KEY (PK), т. (PersonId, SurveyNumber)
Е. И соответствует столбцам Response.PersonId
и Response.SurveyNumber
.
Второй FK указывает на SurveyQuestion
таблицу PK, т. Е. (SurveyNumber, QuestionNumber)
И, соответственно, состоит из столбцов Response.SurveyNumber
и Response.QuestionNumber
.
Таким образом, Response.SurveyNumber
столбец весьма полезен, поскольку он используется как часть ссылки FK в двух разных ограничениях.
С помощью этого метода гарантируется, что система управления базами данных гарантирует ссылочную целостность от
- (а)
Response
к PersonSurvey
;
- (б)
Response
к SurveyQuestion
; и
- (c) каждая из таблиц, представляющих тип ассоциативного объекта для таблиц, обозначающих независимые типы объектов, а именно
Person
, Survey
и Question
.
Производные данные, чтобы избежать обновления аномалий
Я заметил на вашей диаграмме два элемента, которые я считаю заслуживающими упоминания. Эти элементы связаны с двумя PersonSurvey
столбцами, которые могут (должны) быть получены .
В связи с этим, вы можете получить PersonSurvey.IsStarted
данные путем запроса, если конкретное Person
вхождение предоставило одно или несколько значений Responses
для Questions
интегрирования точного Survey
через SurveyQuestion
таблицу.
И вы также можете получить PersonSurvey.IsCompleted
точку данных, определив, предоставил ли данный Person
экземпляр Response
всем, Questions
что совпадает со значением «ИСТИНА» в IsMandatory
столбце в определенной SurveyQuestion
строке.
Путем получения этих значений вы предотвращаете некоторые аномалии обновления, которые могли бы в конечном итоге возникнуть, если бы вы сохранили такие значения в SurveyQuestion
столбце.
Важное соображение
Как правильно заметил в своем комментарии @Dave , если вы столкнетесь с будущим требованием, требующим управления различными типами ответов, которые предполагают управление датами, числовыми значениями, множественным выбором и другими возможными аспектами, вам придется расширить этот макет базы данных.
ID
иNumber
, но в остальном это фантастика. Спасибо.Это одна из причин, почему я не люблю добавлять префиксы к столбцам при переносе их в качестве внешних ключей. В вашем первом случае инструмент моделирования может заставить вас поставить префикс одного из
survey_id
столбцов вsurvey_person_question_response
таблице. Вы можете изменить это после установления отношений.При необходимости удалите избыточное поле идентификатора опроса, когда вы строите физическую модель, где вам не нужен дублированный столбец. Как вы определили, обе ваши модели имеют проблемы, но я считаю, что первая модель в целом лучше.
источник