如何设计一个数据库来表示结构变化的数据?
How to design a database to represent data that changes in structure?
正在设计一个数据库来存储和跟踪 Web 表单内容的历史记录。通常这不是问题。天真的实现是 history
table 记录表单字段内容以及时间戳。
问题是:此表单可能会随着时间的推移而改变。字段可能会被重命名、添加或删除。
如何建模并确保整个历史记录的数据完整性。
我现在的想法是 history
table 可以只用两个字段来完成:timestamp
和 data
。并且,在这种情况下,data
将是一个 JSON 字符串,对应于拍摄快照时的表单字段及其数据。这意味着该软件可以随时显示表单的回滚版本,无论结构如何更改。
在数据库中表示它的其他方法可能是什么?
使用 Python/Django 和 MySQL,这可能不相关。
编辑 1:
澄清。想象一下,想要在您无法控制的网站上记录表单的历史记录。它是关于创建一个数据库来存储和记录该页面的历史记录。想想 Git 一个页面,其表单和数据的结构和内容每一两年都会发生变化。
编辑 2:
一个选择是创建一个复杂的 table 结构,其中可以使用 table 来描述表单,该 table 存储在任何给定时间可用的各种类型的表单字段,然后是 form_contents
或 form_history
table 最终会将它们粘合在一起形成一个结构,该结构可以记录随着时间的推移具有不同结构的表单的历史。我可以看到这可能会变得非常复杂。
如果我理解正确的话,我可能会这样做:
CREATE TABLE IF NOT EXISTS `form_history` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`when` datetime NOT NULL,
`field_accept` varchar(255) DEFAULT NULL,
`field_accesskey` varchar(255) DEFAULT NULL,
`field_alt` varchar(255) DEFAULT NULL,
`field_autocomplete` varchar(255) DEFAULT NULL,
`field_autofocus` varchar(255) DEFAULT NULL,
`field_checked` varchar(255) DEFAULT NULL,
`field_class` varchar(255) DEFAULT NULL,
`field_contenteditable` varchar(255) DEFAULT NULL,
`field_contextmenu` varchar(255) DEFAULT NULL,
`field_data` text DEFAULT NULL,
`field_dir` varchar(255) DEFAULT NULL,
`field_disabled` varchar(255) DEFAULT NULL,
`field_draggable` varchar(255) DEFAULT NULL,
`field_dropzone` varchar(255) DEFAULT NULL,
`field_form` varchar(255) DEFAULT NULL,
`field_formaction` varchar(255) DEFAULT NULL,
`field_formtarget` varchar(255) DEFAULT NULL,
`field_height` int unsigned DEFAULT NULL,
`field_hidden` varchar(255) DEFAULT NULL,
`field_id` varchar(255) DEFAULT NULL,
`field_lang` varchar(255) DEFAULT NULL,
`field_list` varchar(255) DEFAULT NULL,
`field_max` varchar(255) DEFAULT NULL,
`field_maxlength` int unsigned DEFAULT NULL,
`field_min` varchar(255) DEFAULT NULL,
`field_multiple` varchar(255) DEFAULT NULL,
`field_name` varchar(255) DEFAULT NULL,
`field_pattern` varchar(255) DEFAULT NULL,
`field_placeholder` varchar(255) DEFAULT NULL,
`field_readonly` varchar(255) DEFAULT NULL,
`field_required` varchar(255) DEFAULT NULL,
`field_size` int unsigned DEFAULT NULL,
`field_spellcheck` varchar(255) DEFAULT NULL,
`field_src` varchar(255) DEFAULT NULL,
`field_step` int unsigned DEFAULT NULL,
`field_style` varchar(255) DEFAULT NULL,
`field_tabindex` int unsigned DEFAULT NULL,
`field_title` varchar(255) DEFAULT NULL,
`field_translate` varchar(255) DEFAULT NULL,
`field_type` varchar(255) DEFAULT NULL,
`field_value` varchar(255) DEFAULT NULL,
`field_width` int unsigned DEFAULT NULL,
PRIMARY KEY (`id`), KEY (`when`)
) ENGINE=InnoDB COMMENT='Field definitions';
如果这对您很重要,您也可以为事件属性添加列。
下面是一些示例数据:
|----|---------------------|-----|-----------------|-----|------------|-----|
| id | when | ... | field_maxlength | ... | field_name | ... |
|----|---------------------|-----|-----------------|-----|------------|-----|
| 1 | 2015-06-01 00:00:01 | ... | 10 | ... | username | ... |
| 2 | 2015-06-01 00:00:01 | ... | 10 | ... | password | ... |
| .. | ................... | ... | ............... | ... | .......... | ... |
| 17 | 2015-06-08 00:00:01 | ... | 32 | ... | username | ... |
| 18 | 2015-06-08 00:00:01 | ... | 32 | ... | password | ... |
| 19 | 2015-06-08 00:00:01 | ... | 25 | ... | fname | ... |
| 20 | 2015-06-08 00:00:01 | ... | 25 | ... | lname | ... |
| .. | ................... | ... | ............... | ... | .......... | ... |
|----|---------------------|-----|-----------------|-----|------------|-----|
这个非常简单的示例数据仅显示表单上的两个字段(username
和 password
)。在 1 日,他们的 maxlength
都是 10,但在 8 日,他们的 maxlength
值增加到 32,并且在表单中添加了两个新字段:fname
和 lname
.
正在设计一个数据库来存储和跟踪 Web 表单内容的历史记录。通常这不是问题。天真的实现是 history
table 记录表单字段内容以及时间戳。
问题是:此表单可能会随着时间的推移而改变。字段可能会被重命名、添加或删除。
如何建模并确保整个历史记录的数据完整性。
我现在的想法是 history
table 可以只用两个字段来完成:timestamp
和 data
。并且,在这种情况下,data
将是一个 JSON 字符串,对应于拍摄快照时的表单字段及其数据。这意味着该软件可以随时显示表单的回滚版本,无论结构如何更改。
在数据库中表示它的其他方法可能是什么?
使用 Python/Django 和 MySQL,这可能不相关。
编辑 1:
澄清。想象一下,想要在您无法控制的网站上记录表单的历史记录。它是关于创建一个数据库来存储和记录该页面的历史记录。想想 Git 一个页面,其表单和数据的结构和内容每一两年都会发生变化。
编辑 2:
一个选择是创建一个复杂的 table 结构,其中可以使用 table 来描述表单,该 table 存储在任何给定时间可用的各种类型的表单字段,然后是 form_contents
或 form_history
table 最终会将它们粘合在一起形成一个结构,该结构可以记录随着时间的推移具有不同结构的表单的历史。我可以看到这可能会变得非常复杂。
如果我理解正确的话,我可能会这样做:
CREATE TABLE IF NOT EXISTS `form_history` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`when` datetime NOT NULL,
`field_accept` varchar(255) DEFAULT NULL,
`field_accesskey` varchar(255) DEFAULT NULL,
`field_alt` varchar(255) DEFAULT NULL,
`field_autocomplete` varchar(255) DEFAULT NULL,
`field_autofocus` varchar(255) DEFAULT NULL,
`field_checked` varchar(255) DEFAULT NULL,
`field_class` varchar(255) DEFAULT NULL,
`field_contenteditable` varchar(255) DEFAULT NULL,
`field_contextmenu` varchar(255) DEFAULT NULL,
`field_data` text DEFAULT NULL,
`field_dir` varchar(255) DEFAULT NULL,
`field_disabled` varchar(255) DEFAULT NULL,
`field_draggable` varchar(255) DEFAULT NULL,
`field_dropzone` varchar(255) DEFAULT NULL,
`field_form` varchar(255) DEFAULT NULL,
`field_formaction` varchar(255) DEFAULT NULL,
`field_formtarget` varchar(255) DEFAULT NULL,
`field_height` int unsigned DEFAULT NULL,
`field_hidden` varchar(255) DEFAULT NULL,
`field_id` varchar(255) DEFAULT NULL,
`field_lang` varchar(255) DEFAULT NULL,
`field_list` varchar(255) DEFAULT NULL,
`field_max` varchar(255) DEFAULT NULL,
`field_maxlength` int unsigned DEFAULT NULL,
`field_min` varchar(255) DEFAULT NULL,
`field_multiple` varchar(255) DEFAULT NULL,
`field_name` varchar(255) DEFAULT NULL,
`field_pattern` varchar(255) DEFAULT NULL,
`field_placeholder` varchar(255) DEFAULT NULL,
`field_readonly` varchar(255) DEFAULT NULL,
`field_required` varchar(255) DEFAULT NULL,
`field_size` int unsigned DEFAULT NULL,
`field_spellcheck` varchar(255) DEFAULT NULL,
`field_src` varchar(255) DEFAULT NULL,
`field_step` int unsigned DEFAULT NULL,
`field_style` varchar(255) DEFAULT NULL,
`field_tabindex` int unsigned DEFAULT NULL,
`field_title` varchar(255) DEFAULT NULL,
`field_translate` varchar(255) DEFAULT NULL,
`field_type` varchar(255) DEFAULT NULL,
`field_value` varchar(255) DEFAULT NULL,
`field_width` int unsigned DEFAULT NULL,
PRIMARY KEY (`id`), KEY (`when`)
) ENGINE=InnoDB COMMENT='Field definitions';
如果这对您很重要,您也可以为事件属性添加列。
下面是一些示例数据:
|----|---------------------|-----|-----------------|-----|------------|-----|
| id | when | ... | field_maxlength | ... | field_name | ... |
|----|---------------------|-----|-----------------|-----|------------|-----|
| 1 | 2015-06-01 00:00:01 | ... | 10 | ... | username | ... |
| 2 | 2015-06-01 00:00:01 | ... | 10 | ... | password | ... |
| .. | ................... | ... | ............... | ... | .......... | ... |
| 17 | 2015-06-08 00:00:01 | ... | 32 | ... | username | ... |
| 18 | 2015-06-08 00:00:01 | ... | 32 | ... | password | ... |
| 19 | 2015-06-08 00:00:01 | ... | 25 | ... | fname | ... |
| 20 | 2015-06-08 00:00:01 | ... | 25 | ... | lname | ... |
| .. | ................... | ... | ............... | ... | .......... | ... |
|----|---------------------|-----|-----------------|-----|------------|-----|
这个非常简单的示例数据仅显示表单上的两个字段(username
和 password
)。在 1 日,他们的 maxlength
都是 10,但在 8 日,他们的 maxlength
值增加到 32,并且在表单中添加了两个新字段:fname
和 lname
.