Na podstawie tego, co powiedziałeś, użyłbym następującego ogólnego schematu:
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])
)
Naprawdę nie obchodzi cię, czy odpowiedź jest liczbą, datą, słowem itp., Ponieważ dane są odpowiedzią na pytanie, a nie czymś, na co musisz bezpośrednio operować. Ponadto dane mają znaczenie tylko w kontekście pytania. Jako taki nvarchar jest najbardziej wszechstronnym, czytelnym dla człowieka mechanizmem przechowywania danych.
Pytanie i potencjalne odpowiedzi zostaną zebrane od pierwszego użytkownika i wstawione do tabel PollQuestion i PollOption. Drugi użytkownik, który odpowie na pytania, wybierze z listy odpowiedzi (prawda / fałsz = lista 2). Możesz także rozwinąć tabelę PollQuestion, aby w razie potrzeby uwzględnić identyfikator użytkownika twórcy, aby śledzić tworzone przez niego pytania.
W interfejsie użytkownika odpowiedź wybrana przez użytkownika może być powiązana z wartością PollOptionId. Razem z PollQuestionId możesz szybko sprawdzić, czy odpowiedź jest ważna na pytanie. Ich odpowiedź, jeśli jest poprawna, zostanie wpisana do tabeli PollResponse.
Istnieje kilka potencjalnych problemów w zależności od szczegółów twojego przypadku użycia. Jeśli pierwszy użytkownik chce użyć pytania matematycznego, a nie chcesz oferować wielu możliwych odpowiedzi. Inna sytuacja polega na tym, że opcje, które zapewnia początkowy użytkownik, nie są jedynymi opcjami, które może wybrać drugi użytkownik. Możesz przerobić ten schemat w następujący sposób, aby obsługiwać te dodatkowe przypadki użycia.
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])
)
Prawdopodobnie dodałbym również ograniczenie sprawdzania, aby upewnić się, że podano opcję lub odpowiedź alternatywną, ale nie obie (opcja i odpowiedź alternatywna), w zależności od potrzeb.
Edycja: Komunikowanie typu danych dla AlternateResponse.
W idealnym świecie moglibyśmy użyć koncepcji generycznych do obsługi różnych typów danych dla AlternateReponse. Niestety nie żyjemy w idealnym świecie. Najlepszym kompromisem, jaki mogę wymyślić, jest określenie, jaki typ danych AlternateResponse powinien znajdować się w tabeli PollQuestion, i zapisanie AlternateReponse w bazie danych jako nvarchar. Poniżej znajduje się zaktualizowany schemat pytań i nowa tabela typów danych:
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
)
Możesz wyświetlić listę wszystkich dostępnych typów danych dla twórców pytań, wybierając z tej tabeli QuestionDataType. Twój interfejs użytkownika może odwoływać się do klasy QuestionDataTypeId, aby wybrać odpowiedni format dla alternatywnego pola odpowiedzi. Nie jesteś ograniczony do typów danych TSQL, więc „Numer telefonu” może być typem danych i uzyskasz odpowiednie formatowanie / maskowanie w interfejsie użytkownika. Również w razie potrzeby możesz przesłać swoje dane do odpowiednich typów za pomocą prostej instrukcji przypadku w celu wykonania dowolnego rodzaju przetwarzania (wyboru, weryfikacji itp.) Alternatywnych odpowiedzi.