多字段表单的数据库设计
Database design for form with many fields
一个表单包含30-40个不同的字段(将来可能会添加更多,所以这必须是可能的)我需要找到一个好的数据结构将它们保存在数据库中(MS SQL服务器)。这些字段可以有不同的类型,例如复选框 (true/false)、选择(1 到 x 个可能的值可供选择)和文本字段。每种形式都可以通过操作号(字符串)和修订版(int)的组合键来识别。
这里有一个例子,想想更多这些类型的字段:
Example form
我会这样尝试:
- table form
- operation_number nvarchar(255) PK
- revision int PK
- created_at datetime
------------------------------------------------
This will be used for all true/false checkboxes:
- table checkbox_option
- id int PK
- form_operation_number nvarchar(255) FK (for form.operation_number)
- form_revision int FK (for form.revision)
- value bit
------------------------------------------------
This will be used for all text fields (see "Locations" and "Additional comments" in the example):
- table text_option
- id int PK
- form_operation_number nvarchar(255) FK (for form.operation_number)
- form_revision int FK (for form.revision)
- value varchar(max)
------------------------------------------------
This will be used for all selects:
- table select_option_name
- id int PK
- form_operation_number nvarchar(255) FK (for form.operation_number)
- form_revision int FK (for form.revision)
- name string (the text for the label, like "color" in the example)
------------------------------------------------
- table select_option_junction
- select_option_name_id int PK FK (for select_option_name.id)
- select_option_values_id int PK FK (for select_option_value.id)
------------------------------------------------
Table for all the options of a select field:
- table select_option_values
- id int PK
- value nvarchar(255)
这看起来是个不错的设计还是我忘记了一些重要的事情?也许你有更好的主意?谢谢。
id int PK
您会看到很多鼓励这种设计选择的建议。我反对。
首先深入一点。确定每列的域。决定它与表格的关系。表单中可能出现不止一个值的任何列(例如,销售订单中的订单项目)进入另一个 table,通过外键与表单相关。
找出任何行中的哪些值唯一标识该行,即将它与所有其他行区分开来。那是一个自然键。通过使用自然键,您被迫了解数据的基数,并启用 DBMS 来执行它。
例如,您的颜色列将包含所有可能颜色的 table,一个 域 table。您可以使用颜色名称作为主键,因为没有两种颜色具有相同的名称。然后,在您的表单 table 中,您有一个带有颜色 table 外键的颜色列。如果用户以某种方式尝试插入 form-table 颜色不在颜色 table 中的行,DBMS 将拒绝它并违反外键。
如果 OTOH 您选择使用 id int PK 作为颜色的主键 table,没有什么可以阻止“蓝色”在table,可能是 id 7 和 17。为防止这种情况,您必须进行定义自然键所需的相同分析。添加代理项 id 键只会增加工作量。
自然键也更容易使用。
使用 id 主键,您的 form-table 在颜色列中只有一个不透明的数字。如果您使用自然键,您会看到“红色”而不是 11。
有人会警告您自然键可以更改。例如,一个人的名字可能会改变。这通常证明该列实际上不是自然键。更重要的是:如果你在数据中缺少一个可靠的例子,那么当 stable 数据改变的可能性发生时,任何设计努力都可能证明是不充分的(而且是错误的),如果它确实发生了。
有些情况下不存在或似乎不存在自然键。有时,与杂货或库存一样,无法区分的项目可以通过在数量栏中进行计数来计算。对于随时间变化(并随时间保留)的行,向键添加日期通常有效。
不过,有时您会向数据库中添加一些全新的内容,这些内容是任何人都懒得说出来的。 那是你需要发明一把钥匙的时候。
一个表单包含30-40个不同的字段(将来可能会添加更多,所以这必须是可能的)我需要找到一个好的数据结构将它们保存在数据库中(MS SQL服务器)。这些字段可以有不同的类型,例如复选框 (true/false)、选择(1 到 x 个可能的值可供选择)和文本字段。每种形式都可以通过操作号(字符串)和修订版(int)的组合键来识别。
这里有一个例子,想想更多这些类型的字段: Example form
我会这样尝试:
- table form - operation_number nvarchar(255) PK - revision int PK - created_at datetime ------------------------------------------------ This will be used for all true/false checkboxes: - table checkbox_option - id int PK - form_operation_number nvarchar(255) FK (for form.operation_number) - form_revision int FK (for form.revision) - value bit ------------------------------------------------ This will be used for all text fields (see "Locations" and "Additional comments" in the example): - table text_option - id int PK - form_operation_number nvarchar(255) FK (for form.operation_number) - form_revision int FK (for form.revision) - value varchar(max) ------------------------------------------------ This will be used for all selects: - table select_option_name - id int PK - form_operation_number nvarchar(255) FK (for form.operation_number) - form_revision int FK (for form.revision) - name string (the text for the label, like "color" in the example) ------------------------------------------------ - table select_option_junction - select_option_name_id int PK FK (for select_option_name.id) - select_option_values_id int PK FK (for select_option_value.id) ------------------------------------------------ Table for all the options of a select field: - table select_option_values - id int PK - value nvarchar(255)
这看起来是个不错的设计还是我忘记了一些重要的事情?也许你有更好的主意?谢谢。
id int PK
您会看到很多鼓励这种设计选择的建议。我反对。
首先深入一点。确定每列的域。决定它与表格的关系。表单中可能出现不止一个值的任何列(例如,销售订单中的订单项目)进入另一个 table,通过外键与表单相关。
找出任何行中的哪些值唯一标识该行,即将它与所有其他行区分开来。那是一个自然键。通过使用自然键,您被迫了解数据的基数,并启用 DBMS 来执行它。
例如,您的颜色列将包含所有可能颜色的 table,一个 域 table。您可以使用颜色名称作为主键,因为没有两种颜色具有相同的名称。然后,在您的表单 table 中,您有一个带有颜色 table 外键的颜色列。如果用户以某种方式尝试插入 form-table 颜色不在颜色 table 中的行,DBMS 将拒绝它并违反外键。
如果 OTOH 您选择使用 id int PK 作为颜色的主键 table,没有什么可以阻止“蓝色”在table,可能是 id 7 和 17。为防止这种情况,您必须进行定义自然键所需的相同分析。添加代理项 id 键只会增加工作量。
自然键也更容易使用。 使用 id 主键,您的 form-table 在颜色列中只有一个不透明的数字。如果您使用自然键,您会看到“红色”而不是 11。
有人会警告您自然键可以更改。例如,一个人的名字可能会改变。这通常证明该列实际上不是自然键。更重要的是:如果你在数据中缺少一个可靠的例子,那么当 stable 数据改变的可能性发生时,任何设计努力都可能证明是不充分的(而且是错误的),如果它确实发生了。
有些情况下不存在或似乎不存在自然键。有时,与杂货或库存一样,无法区分的项目可以通过在数量栏中进行计数来计算。对于随时间变化(并随时间保留)的行,向键添加日期通常有效。
不过,有时您会向数据库中添加一些全新的内容,这些内容是任何人都懒得说出来的。 那是你需要发明一把钥匙的时候。