如何设计数据库来表示结构发生变化的数据?

时间:2015-06-07 18:24:41

标签: python mysql database database-design

设计数据库以存储和跟踪Web表单内容的历史记录。通常这不是问题。天真的实现是一个history表,它记录表单字段内容以及时间戳。

问题在于:此表单可能会随着时间的推移而发生变化。可以重命名,添加或删除字段。

如何建模并确保整个历史记录中的数据完整性。

我现在的想法是history表格只需两个字段即可完成:timestampdata。并且,在这种情况下,data将是一个JSON字符串,对应于表单字段及其拍摄快照时的数据。这意味着软件可以随时显示表单的回滚版本,无论结构如何变化。

在数据库中表示这一点的其他方法是什么?

使用Python / Django和MySQL,这可能不相关。

编辑1:

澄清。想象一下,想要在您无法控制的网站上记录表单的历史记录。它是关于创建一个数据库来存储和记录该页面的历史记录。想想一个页面,其中的表单和数据每年或每两年都会改变结构和内容。

编辑2:

一种选择是创建一个复杂的表结构,通过使用一个表来存储表单,该表存储在任何给定时间可用的各种类型的表单字段,然后是form_contentsform_history table最终将它们粘合在一起,形成一个可以记录随时间变化的结构形式的历史的结构。我可以看到这可能变得非常复杂。

1 个答案:

答案 0 :(得分:3)

如果我理解正确,我可能会这样做:

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      | ... |
| .. | ................... | ... | ............... | ... | .......... | ... |
|----|---------------------|-----|-----------------|-----|------------|-----|

这个非常简单的示例数据仅显示表单上的两个字段(usernamepassword)。在1日,他们都有maxlength 10,但在8日他们将maxlength值增加到32,并在表单中添加了两个新字段:fname和{{1} }。