あなたの仕様を理解しているように、ビジネス環境には概念レベルの三項関係が含まれます。これに関して、次のことを定義する必要があります。
- エンティティタイプPersonとSurvey間の関係(または関連)タイプ。
- 調査と質問の関係タイプ。
- 前述の2つの関係タイプ間の関係を確立する関係タイプ、および結果として、Person、Survey、およびQuestion間の関係、つまり、Response(私の観点から、解釈を簡略化する短い名前)。
したがって、アプローチ1は正しい方向に進んでいると思いますが、より正確にするためにはいくつかの(しかし重要な)微調整が必要です。次のセクションでは、そのような改良点とその他の関連する考慮事項について詳しく説明します。
ビジネスルール
適用可能なビジネスルールを少し拡張して、次のように再定式化しましょう。
- A 人物ゼロ・ワン・オア・多くのレジスタ調査
- A 調査は、ゼロ・ワン・オア・多くの登録取得者を
- A 調査は、 1対多で統合されている質問
- A 質問は、ゼロ・ワン・オア・多くの統合調査を
- A 質問は、ゼロ・ワン・オア・多くの受信応答を
- A 応答は、正確に-1によって提供される人に正確-1のコンテキストで調査
解説IDEF1X図
次に、図1に示すIDEF1X ダイアグラムを作成しました。これは、上記で定式化されたビジネスルールを統合したものです。
インフォメーションモデリングのための統合の定義( IDEF1Xは)として設立された非常にお勧めのモデル化技術である標準米国国立標準技術研究所(で1993年12月に NIST)。これは、リレーショナルモデルの唯一の創設者である EF Codd博士によって作成された理論的研究、および PP Chen博士によって開発されたエンティティ関係ビューにしっかりと基づいています。
PersonSurvey関係
私が見ているように、PersonSurvey関係は、Personが特定のSurveyに参加できるように承認の手段を提供する必要があります。このように、特定の調査に特定の人物が登録されると、その人物は、それぞれの調査を統合する質問に回答する権限を与えられます。
SurveyQuestionの関係
ダイアグラムでsuvery_question.question_numberと呼ばれるプロパティ(または属性)が、特定のSurveyに関する特定のQuestionインスタンスの表示順序を表すために使用されていると思います。ご覧のとおり、このようなプロパティをSurveyQuestion.PresentationOrderと示しましたが、(i)2つ以上のQuestion.QuestionNumber値が(ii)同じPresentationOrder値を(iii)同じSurveyQuestionで共有しないようにする必要があると思います。
その必要性を表現するために、このエンティティタイプを表すボックスに複合の代替キー(AK)を含めました。これは、プロパティの組み合わせ(SurveyNumber、QuestionNumber、PresentationOrder)で構成されています。ご存じのとおり、複合AKは、複数列のUNIQUE制約を使用して論理DDL設計で宣言できます(SurveyQuestion
説明用のDDLレイアウトの一部である表で例示したように、以下のいくつかのセクションで説明しています)。
レスポンスエンティティタイプ
はい、Responseエンティティタイプでは、他の2つの関係間の関係を示しています。それが可能であれば()ビジネス正確に関心のコンテキストと、(b)の機能は論理レベルのレイアウトで適切に表現さを表すように、一見厄介なようですが、このアプローチには何も間違っているがあります。
はい、あなたは完全に正しいです。同じ行の2つの異なる列から参照される2 つの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
テーブル内の2つの複合外部キー
これはおそらく、議論する最も重要なポイントです。特定のResponse
行から
SurveyQuestion.SurveyNumber
、および
SurveyPerson.SurveyNumber
一致する値が必要です。私に関する限り、宣言的な方法でこの条件を強制する最良のオプションは、2つの複合外部キー(FK)を使用することです。
DDL設計に示されるように、最初のFKを参照製造されPersonSurvey
、すなわち、テーブルPRIMARY KEY(PK)を(PersonId, SurveyNumber)
、列によって適合されるResponse.PersonId
とResponse.SurveyNumber
。
2番目のFKはSurveyQuestion
テーブルPK、つまりを指しており(SurveyNumber, QuestionNumber)
、したがって列Response.SurveyNumber
とで構成されていますResponse.QuestionNumber
。
このように、2つの異なる制約Response.SurveyNumber
でFK参照の一部として使用されるため、列は非常に役立ちます。
この方法では、データベース管理システムが保証する参照整合性を
- (a)
Response
にPersonSurvey
;
- (b)
Response
にSurveyQuestion
; そして
- (c)独立したエンティティタイプを表すテーブルへの関連エンティティタイプを表す各テーブル、つまり
Person
、Survey
およびQuestion
。
更新の異常を回避するための派生データ
あなたの図で、私が言及する価値がある2つの要素に気づきました。これらの要素はPersonSurvey
、派生できる(する必要がある)2つの列に関連しています。
その点でPersonSurvey.IsStarted
、特定のPerson
オカレンスがテーブルを介して完全に統合する1つ以上Responses
を提供しているかどうかを照会することにより、データを導出できます。Questions
Survey
SurveyQuestion
また、特定の行の列に「TRUE」の値を含むすべてのインスタンスにPersonSurvey.IsCompleted
特定のPerson
インスタンスがを提供したかどうかを判断することによって、データポイントを取得することもできます。Response
Questions
IsMandatory
SurveyQuestion
これらの値の導出により、そのような値をSurveyQuestion
列に保持していた場合に最終的に発生する可能性がある更新の異常を防止しています。
重要な考慮事項
以下のよう@Daveは当然彼のコメントで指摘あなたが管理し、日付、数値、複数の選択肢、および他の可能な側面を意味するものでは応答の異なる種類の管理を要求し、将来の要件に直面した場合、あなたはこのデータベースのレイアウトを拡張する必要があります。
ID
で終わっていると少し混乱しましたNumber
が、それ以外の場合はこれは素晴らしいです。ありがとうございました。