Исходя из того, что вы сказали, я бы использовал следующую общую схему:
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. Второй пользователь, который отвечает на вопросы, будет выбирать из списка ответов (true / false = список из 2). Вы также можете расширить таблицу PollQuestion, включив, при необходимости, идентификатор пользователя создателя, чтобы отслеживать вопросы, которые они создают.
В вашем пользовательском интерфейсе ответ, выбранный пользователем, может быть привязан к значению PollOptionId. Вместе с PollQuestionId вы можете быстро проверить, что ответ действителен для вопроса. Их ответ, если он действителен, будет занесен в таблицу PollResponse.
Есть несколько потенциальных проблем в зависимости от деталей вашего варианта использования. Если первый пользователь хочет использовать математический вопрос, и вы не хотите предлагать несколько возможных ответов. Другая ситуация, если параметры, которые предоставляет первоначальный пользователь, не являются единственными параметрами, которые может выбрать второй пользователь. Вы можете переработать эту схему следующим образом, чтобы поддержать эти дополнительные варианты использования.
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. Увы, мы не живем в идеальном мире. Лучший компромисс, о котором я могу подумать, - это указать, какой тип данных AlternateResponse должен быть в таблице PollQuestion, и сохранить 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. Ваш пользовательский интерфейс может ссылаться на QuestionDataTypeId, чтобы выбрать правильный формат для альтернативного поля ответа. Вы не ограничены типами данных TSQL, поэтому «Номер телефона» может быть типом данных, и вы получите соответствующее форматирование / маскирование в пользовательском интерфейсе. Также, если необходимо, вы можете привести ваши данные к соответствующим типам с помощью простого оператора case для выполнения любого вида обработки (выбор, проверка и т. Д.) Альтернативных ответов.