De acordo com meu entendimento de suas especificações, seu ambiente de negócios envolve um relacionamento ternário em nível conceitual . Nesse sentido, você precisa definir:
- o tipo de relacionamento (ou associação ) entre os tipos de entidade Pessoa e Pesquisa ;
- o tipo de relação entre pesquisa e pergunta ;
- o tipo de relacionamento que estabelece a conexão entre os dois tipos de relacionamento acima mencionados e, como conseqüência, entre Pessoa , Pesquisa e Pergunta , ou seja, Resposta (um nome mais curto que simplifica a interpretação, do meu ponto de vista).
Portanto, considero que você está no caminho certo com sua Abordagem 1 , embora exija alguns refinamentos pequenos (mas importantes) para torná-la mais precisa. Vou detalhar esses refinamentos e outras considerações relevantes nas seções a seguir.
Regras do negócio
Vamos expandir um pouco as regras de negócios aplicáveis e reformulá-las da seguinte maneira:
- Uma Pessoa registros em zero-um ou-muitas Surveys
- Uma pesquisa obtém o registro de zero-uma-ou-muitas pessoas
- Uma pesquisa é integrada por perguntas um-para-muitos
- A questão integra-zero um ou-muitos Surveys
- Uma pergunta recebe zero-uma-ou-muitas respostas
- Uma resposta é fornecida por exatamente uma pessoa no contexto de exatamente uma pesquisa
Diagrama do IDEF1X expositivo
Em seguida, criei o IDEF1X, um diagrama que é apresentado na Figura 1 , que sintetiza as regras de negócios formuladas acima:
a Definição de integração para Information Modeling ( IDEF1X ) é uma técnica de modelagem altamente recomendável que foi estabelecido como um padrão em Dezembro de 1993 pelo Instituto Estados Unidos Nacional de Padrões e Tecnologia ( NIST ). Baseia-se solidamente no trabalho teórico de autoria do único fundador do modelo relacional , o Dr. EF Codd, e também na visão de entidade-relacionamento desenvolvida pelo Dr. PP Chen .
O relacionamento PersonSurvey
A meu ver, é necessário que o relacionamento do PersonSurvey forneça um meio de autorização para que uma Pessoa possa participar de uma determinada Pesquisa . Dessa forma, uma vez que uma determinada pessoa tenha sido registrada em uma pesquisa específica , ela estará autorizada a fornecer respostas às perguntas que integram a respectiva pesquisa .
O relacionamento SurveyQuestion
Suponho que a propriedade (ou atributo) chamada suvery_question.question_number em seu diagrama seja usada para representar a ordem de apresentação de uma determinada instância de questão em relação a uma pesquisa específica . Como você pode ver, eu denotei essa propriedade como SurveyQuestion.PresentationOrder e acho que você deve impedir que (i) dois ou mais valores de Question.QuestionNumber compartilhem (ii) o mesmo valor PresentationOrder em (iii) a mesma ocorrência SurveyQuestion .
Para retratar essa necessidade, incluí uma ALTERNATE KEY (AK) na caixa que representa esse tipo de entidade, composta pela combinação de propriedades ( SurveyNumber, QuestionNumber, PresentationOrder ). Como você bem sabe, um AK composto pode ser declarado em um design DDL lógico com o auxílio de uma restrição UNIQUE de várias colunas (como exemplifiquei na SurveyQuestion
tabela que faz parte do layout DDL expositivo exposto algumas seções abaixo).
O tipo de entidade Resposta
Sim, com o tipo de entidade Resposta , estou representando um relacionamento entre dois outros relacionamentos ; isso pode parecer estranho à primeira vista, mas não há nada de errado com essa abordagem, desde que (a) representa as características do contexto de negócios de interesse com precisão e (b) é representado adequadamente em um layout de nível lógico.
Sim, você está totalmente correto, seria um erro retratar essa parte do cenário no nível lógico de abstração por meio de dois Response.SurveyNumber
(ou, digamos Response.SurveyId
) valores referenciados de duas colunas diferentes na mesma Response
linha.
Layout SQL-DDL lógico derivado
-- 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)
);
Duas CHAVES ESTRANGEIRAS compostas na Response
tabela
Este é, provavelmente, o ponto mais importante a ser discutido: as referências feitas de uma determinada Response
linha para
SurveyQuestion.SurveyNumber
e
SurveyPerson.SurveyNumber
deve ter valores correspondentes . No que me diz respeito, a melhor opção para impor essa condição de maneira declarativa é usar duas FOREIGN KEYs (FKs) compostas.
Conforme mostrado no design do DDL, o primeiro FK está fazendo uma referência à PersonSurvey
tabela PRIMARY KEY (PK), isto é (PersonId, SurveyNumber)
, e é formado pelas colunas Response.PersonId
e Response.SurveyNumber
.
O segundo FK está apontando para a SurveyQuestion
tabela PK, ou seja,, (SurveyNumber, QuestionNumber)
e é, portanto, composto pelas colunas Response.SurveyNumber
e Response.QuestionNumber
.
Dessa forma, a Response.SurveyNumber
coluna é bastante instrumental, pois é usada como parte de uma referência FK em duas restrições diferentes.
Com este método, assegura a gestão da base de dados sistema de garantia de integridade referencial de
- (a)
Response
para PersonSurvey
;
- (b)
Response
para o SurveyQuestion
; e
- (c) cada uma das tabelas que representam um tipo de entidade associativa às tabelas que representam tipos de entidades independentes, a saber
Person
, Survey
e Question
.
Dados derivados para evitar anomalias de atualização
Notei no seu diagrama dois elementos que considero dignos de menção. Esses elementos estão relacionados a duas PersonSurvey
colunas que podem (devem) ser derivadas .
Nesse sentido, você pode derivar o PersonSurvey.IsStarted
dado consultando se uma determinada Person
ocorrência forneceu um ou mais desses elementos Responses
para Questions
integrar exatamente Survey
por meio da SurveyQuestion
tabela.
E você também pode obter o PersonSurvey.IsCompleted
ponto de dados determinando se uma determinada Person
instância forneceu a Response
a todos os Questions
que possuem um valor 'TRUE' na IsMandatory
coluna em uma SurveyQuestion
linha específica .
Por meio da derivação desses valores, você está impedindo algumas anomalias de atualização que eventualmente surgiriam caso você mantivesse esses valores na SurveyQuestion
coluna.
Consideração importante
Como o @Dave salienta corretamente em seu comentário, se você enfrentar um requisito futuro exigindo o gerenciamento de diferentes tipos de respostas que impliquem gerenciamento de datas, valores numéricos, múltipla escolha e outros possíveis aspectos, você terá que estender esse layout do banco de dados.
ID
eNumber
, mas por outro lado isso é fantástico. Obrigado.Essa é uma das razões pelas quais não gosto de prefixar colunas ao migrá-las como chaves estrangeiras. No seu primeiro caso, a ferramenta de modelagem pode forçar você a prefixar uma das
survey_id
colunas nasurvey_person_question_response
tabela. Você poderá ajustar isso depois que o relacionamento for estabelecido.Se necessário, remova o campo de ID de pesquisa redundante ao criar o modelo físico no qual você não precisa da coluna duplicada. Como você identificou, os dois modelos têm problemas, mas acredito que o primeiro modelo seja melhor no geral.
fonte