在1个或多个表中存储单个表单表问题

时间:2019-01-30 15:19:37

标签: sql tsql database-design database-normalization

我已经在Web应用程序内部编写ASP.NET表单很长时间了。通常,大多数Web应用程序都有一个用户登录,选择要填写的表格并回答问题,因此您的表格看起来像这样

Table: tblInspectionForm
Fields:
inspectionformid (either autoint or guid)
userid (user ID who entered it)
datestamp (added, modified, whatever)
Question1Answer: boolean (maybe a yes/no)
Question2Answer: int (maybe foreign key for sub table 1 with dropdown values)
Question3Answer: int (foreign key for sub table 2 with dropdown values)

如果我没记错的话,它既符合第二范式也适用于第三范式。您没有在表中存储用户名,仅在ID中存储用户名。您不会在Q-3中存储下拉列表或“是/否”值,而不会存储其他表的ID。

但是, IF 所有问题都是完全相同的数据类型(假设没有Q1或Q1也是一个整数),它们链接到完全相同的外键(例如,一个具有20个字符的表格)都是1-10的问题,或者有相同的答案可供选择),这样做会更好吗?

so .. Table: tblInspectionForm
userid (user ID who entered it)
datestamp (added, modified, whatever)
... and that's it for table 1 .. then

Table2: tblInspectionAnswers
inspectionformid (composite key that links back to table1 record)
userid (composite key that links back to table1 record)
datastamp  (composite key that links back to table1 record)
QuestionIDNumber: int (question 1, question 2, question3)
QuestionAnswer: int (foreign key)

这不仅适用于对单个表格仅具有相同类型答案的表格。也许您的表格在1-10个评分(int)中有10个,在布尔值中有10个问题,然后是10个自由格式。.您可以将其分为三个表格。

缺点是,保存表单时,您要为表单上的每个问题拨打1个电话。好处是,如果您有大量夜间整合或复制操作可以提取数据,并且您决定添加一个新问题,则不必手动修改任何复制报告数据源或旨在读取数据的任何其他内容/查询您的表单数据。如果您最初有20个问题,然后将更改部署到应用程序中添加了第21个问题,则该更改将自动进入任何外部复制,数据源,并报告查询此数据的信息。另一个优点是,如果您有一个非常长的时间(在房地产行业中,当您的检查表中有100多个问题超出表格行的8k限制时,这种情况可能会发生很多),您最终不会遇到问题

这种情况是否曾经是保存表单数据的首选方式?

3 个答案:

答案 0 :(得分:1)

根据经验,每当您看到一组名称中带有数字的列时,您就会知道该数据库的设计欠佳。
在大多数情况下,您想要做的是拥有一个表格/问卷调查表,一个问题表,一个潜在答案表(用于多项选择题)以及一个用户选择答案的表。
您可能还需要一个用于问题类型的表格(即自由文本,多项选择,是/否)。 基本上,架构应如下所示:

create table Forms
(
    id int identity(1,1) not null primary key,
    name varchar(100) not null, -- with a unique index
    -- other form related fields here
)
create table QuestionTypes
(
    id int identity(1,1) not null primary key,
    name varchar(100) not null, -- with a unique index
)

create table Questions
(
    id int identity(1,1) not null primary key,
    form_id int not null foreign key references Forms(id),
    type_id int not null foreign key references QuestionTypes(id),
    content varchar(1000)
)

create table Answers
(
    id int identity(1,1) not null primary key,
    question_id int not null foreign key references Questions(id),
    content varchar(1000)
    -- For quizez, unremark the next row:
    -- isCorrect bit not null
)

create table Results
{
    id int identity(1,1) not null primary key,
    form_id int not null foreign key references Forms(id)
    -- in case only registered users can fill the form, unremark the next row
    --user_id int not null foreign key references Users(id), 
}

create table UserAnswers
(
    result_id int not null foreign key references Results(id), 
    question_id int not null foreign key references Questions(id), 
    answer_id int not null foreign key references Answers(id),
    content varchar(1000) null -- for free text questions
)

此设计在生成表单时将需要一些联接(如果每个应用程序有多个表单,则只需添加一个表单可以引用的应用程序表),并通过一些联接来获得结果,但这是最好的我知道动态表单数据库设计。

答案 1 :(得分:0)

我不确定是否“首选”该格式,但我肯定已经看到该格式用于商业用途。

您可能会通过多个答案列(answer_int,answer_varchar,answer_datetime)使辅助表更加灵活,并分配一个您可以用来从右边的列中获取答案的问题值。

因此,如果q_var = 2您知道要在answer_varchar中查找,而q_value = 1您知道是int且需要查找(其名称也可以与问题一起指定并存储在列中)。

我现在使用一个应用程序,以这种方式将答案分为组合框,文本字段,数字,日期等。该应用程序实际上使用JSON形式,将其保存到单独的列中时将数据拆分。有点缺陷,因为它将JSON保存到这些列中,但是原理可以工作。

答案 2 :(得分:0)

您可以为子表将引用的父表键添加一个标识字段。