duanluwei9374 2013-11-13 19:10
浏览 77

MySQL与InnoDB版本控制行

I would like to have a way of controlling/tracking revisions of rows. I am trying to find the best solution for this problem.

The first thing that comes to mind is to have a table with a id to identify the row and and id for the revision number. The combined ids would be the primary key. so example data might look like this:

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

How can I create a table with this behavior? or is there a better solution to do this?

I like InnoDB since it supports transactions, foreign keys and full text in MySQL 5.6+.

I know its possible to "force" this behavior by how I insert the data but I'm wondering if there is a way to have the table do this automatically.

  • 写回答

2条回答 默认 最新

  • dongyong5912 2013-11-13 19:26
    关注

    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");
    
    评论

报告相同问题?

悬赏问题

  • ¥50 如何增强飞上天的树莓派的热点信号强度,以使得笔记本可以在地面实现远程桌面连接
  • ¥15 MCNP里如何定义多个源?
  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏