あなたが言ったことに基づいて、私は次の一般的なスキーマを使用します:
CREATE TABLE [dbo].[PollQuestion]
(
[PollQuestionId] INT NOT NULL PRIMARY KEY IDENTITY,
[QuestionText] NVARCHAR(150) NOT NULL, -- Some reasonable character limit
[Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
[Archived] DATETIME2(2) NULL, -- Remove this if you don't need to hide questions
)
CREATE TABLE [dbo].[PollOption]
(
[PollOptionId] INT NOT NULL PRIMARY KEY IDENTITY,
[PollQuestionId] INT NOT NULL, -- Link to the question here because options aren't shared across questions
[OptionText] NVARCHAR(50) NOT NULL, -- Some reasonable character limit
[Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
[Archived] DATETIME2(2) NULL -- Remove this if you don't need to hide options
CONSTRAINT [FK_PollOption_PollQuestionId_to_PollQuestion_PollQuestionId] FOREIGN KEY ([PollQuestionId]) REFERENCES [dbo].[PollQuestion]([PollQuestionId])
)
CREATE TABLE [dbo].[PollResponse]
(
[PollResponseId] INT NOT NULL PRIMARY KEY IDENTITY,
[PollOptionId] INT NOT NULL,
[UserId] INT NOT NULL,
[Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
[Archived] DATETIME2(2) NULL, -- Remove this if you don't need to hide answers
CONSTRAINT [FK_PollResponse_PollOptionId_to_PollOption_PollOptionId] FOREIGN KEY ([PollOptionId]) REFERENCES [dbo].[PollOption]([PollOptionId]),
CONSTRAINT [FK_PollResponse_UserId_to_User_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User]([UserId])
)
回答が数字、日付、単語などであるかどうかは問題ではありません。データは、直接操作する必要のない質問に対する回答です。さらに、データは質問との関連でのみ意味があります。このように、nvarcharは、データを格納するための人間が読める最も用途の広いメカニズムです。
質問と潜在的な回答は最初のユーザーから収集され、PollQuestionテーブルとPollOptionテーブルに挿入されます。質問に回答する2番目のユーザーは、回答のリストから選択します(true / false = 2つのリスト)。PollQuestionテーブルを展開して、作成した質問を追跡するために、必要に応じて作成者のユーザーIDを含めることもできます。
UIでは、ユーザーが選択した回答をPollOptionId値に関連付けることができます。PollQuestionIdと一緒に使用すると、回答が質問に対して有効であることをすばやく確認できます。有効な場合の応答は、PollResponseテーブルに入力されます。
ユースケースの詳細に応じて、いくつかの潜在的な問題があります。最初のユーザーが数学の質問を使用したいが、複数の可能な答えを提供したくない場合。別の状況は、最初のユーザーが提供するオプションが、2番目のユーザーが選択できる唯一のオプションではない場合です。これらの追加のユースケースをサポートするために、次のようにこのスキーマを作り直すことができます。
CREATE TABLE [dbo].[PollResponse]
(
[PollResponseId] INT NOT NULL PRIMARY KEY IDENTITY,
[PollOptionId] INT NULL,
[PollQuestionId] INT NOT NULL,
[UserId] INT NOT NULL,
[AlternateResponse] NVARCHAR(50) NULL, -- Some reasonable character limit
[Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
[Archived] DATETIME2(2) NULL, -- Remove this if you don't need to hide answers
CONSTRAINT [FK_PollResponse_PollOptionId_to_PollOption_PollOptionId] FOREIGN KEY ([PollOptionId]) REFERENCES [dbo].[PollOption]([PollOptionId]),
CONSTRAINT [FK_PollResponse_UserId_to_User_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User]([UserId])
)
また、必要に応じて、オプションが提供されるか、または代替応答のいずれかが提供されることを確認するために、チェック制約を追加することもできますが、両方ではありません(オプションと代替応答)。
編集:AlternateResponseの通信データ型。
完全な世界では、ジェネリックの概念を使用して、AlternateReponseのさまざまなデータ型を処理できます。残念ながら、私たちは完璧な世界に住んでいません。私が考えることができる最良の妥協案は、PollQuestionテーブルでAlternateResponseデータ型を指定し、AlternateReponseをnvarcharとしてデータベースに格納することです。以下は、更新された質問スキーマと新しいデータ型テーブルです。
CREATE TABLE [dbo].[PollQuestion]
(
[PollQuestionId] INT NOT NULL PRIMARY KEY IDENTITY,
[QuestionText] NVARCHAR(150) NOT NULL, -- Some reasonable character limit
[QuestionDataTypeId] INT NOT NULL,
[Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
[Archived] DATETIME2(2) NULL, -- Remove this if you don't need to hide questions
-- Insert FK here for QuestionDataTypeId
)
CREATE TABLE [dbo].[QuestionDataType]
(
[QuestionDataTypeId] INT NOT NULL PRIMARY KEY IDENTITY,
[Description] NVARCHAR(50) NOT NULL, -- Some reasonable character limit
)
このQuestionDataTypeテーブルから選択することで、質問作成者が使用できるすべてのデータ型をリストできます。UIはQuestionDataTypeIdを参照して、代替応答フィールドの適切な形式を選択できます。TSQLデータ型に限定されないため、「電話番号」をデータ型にすることができ、UIで適切なフォーマット/マスキングを取得できます。また、必要に応じて、単純なcaseステートメントを使用してデータを適切なタイプにキャストし、代替の回答に対してあらゆる種類の処理(選択、検証など)を実行できます。