0

我想要一种控制/跟踪行修订的方法。我正在努力为这个问题找到最好的解决方案。

首先想到的是有一个带有 id 的表来标识行和 id 用于修订号。组合的 id 将是主键。所以示例数据可能如下所示:

1, 0, "original post" 1, 1, "modified post" 1, 2, "modified again post"

如何创建具有这种行为的表?还是有更好的解决方案来做到这一点?

我喜欢 InnoDB,因为它支持 MySQL 5.6+ 中的事务、外键和全文。

我知道通过插入数据的方式可以“强制”这种行为,但我想知道是否有办法让表自动执行此操作。

4

2 回答 2

1

Consider table structure:

TABLE posts
  post_id INT AUTO_INCREMENT PK
  cur_rev_id INT FK(revisions.rev_id)

TABLE revisions
  rev_id INT AUTO_INCREMENT PK
  orig_post INT FK(posts.post_id)
  post_text VARCHAR

Where the posts table tracks non-versioned information about the post and its current revision, and revisions tracks each version of the post text with a link back to the parent post. Because of the circular FK constraints you'd need to enclose new post insertions in a transaction.

With this you should be able to easily add, remove, track, roll back, and preview revisions to your posts.

Edit:

Yeah, enclosing in a transaction won't exactly help since the keys are set to AUTO_INCREMENT, so you need to dip back in to PHP with LAST_INSERT_ID() and some temporarily NULL indexes.

CREATE TABLE `posts` (
    `post_id` INT(10) NOT NULL AUTO_INCREMENT,
    `cur_rev_id` INT(10) NULL DEFAULT NULL,
    `post_title` VARCHAR(50) NULL DEFAULT NULL,
    PRIMARY KEY (`post_id`),
    INDEX `FK_posts_revisions` (`cur_rev_id`),
) ENGINE=InnoDB

CREATE TABLE `revisions` (
    `rev_id` INT(10) NOT NULL AUTO_INCREMENT,
    `orig_post` INT(10) NULL DEFAULT NULL,
    `post_text` VARCHAR(32000) NULL DEFAULT NULL,
    PRIMARY KEY (`rev_id`),
    INDEX `FK_revisions_posts` (`orig_post`),
) ENGINE=InnoDB

ALTER TABLE `posts`
    ADD CONSTRAINT `FK_posts_revisions` FOREIGN KEY (`cur_rev_id`) REFERENCES `revisions` (`rev_id`);
ALTER TABLE `revisions`
    ADD CONSTRAINT `FK_revisions_posts` FOREIGN KEY (`orig_post`) REFERENCES `posts` (`post_id`);

Then:

$db_engine->query("INSERT INTO posts (cur_rev_id, post_title) VALUES (NULL, 'My post Title!')");
$post_id = $db_engine->last_insert_id();

$db_engine->query("INSERT INTO revisions (orig_post, post_text) VALUES($post_id, 'yadda yadda')");
$rev_id = $db_engine->last_insert_id();

$db_engine->query("UPDATE posts SET cur_rev_id = $rev_id WHERE post_id = $post_id");
于 2013-11-13T19:26:12.193 回答
0

如果我对您的理解正确并且该表没有收到大量更新/删除,那么您可以查看设置触发器,例如:

DELIMITER $$
CREATE TRIGGER t_table_update BEFORE UPDATE ON table_name
FOR EACH ROW
    INSERT INTO table_name_revisions (item_id, data, timestamp) 
        VALUES(OLD.id, OLD.data, NOW());
END$$
DELIMITER ;

有关详细信息,请参阅触发器语法

于 2013-11-13T19:35:46.773 回答