草庐IT

mysql - 加速或自动创建历史表触发器

coder 2023-10-12 原文

是否有任何有用的工具或技巧可以自动(或快速)为 MySQL 中的给定表创建历史表和触发器? I've come across this tool so far ,但是好久没更新了。如果相关,我会使用 MySQL Workbench 的“模型”工具来构建我的数据库模型,然后将它们与我的本地数据库同步。

我想要的是能够提供表的创建脚本,并让工具神奇地吐出历史表的创建脚本和触发器,以便在插入/更新/删除时插入到这些历史表中。例如,如果我的表 foo 具有复合 PK ab、外键 c d 和属性 ef,它将为历史表 foo_history 生成具有复合 PK a 的创建脚本brevisionNumcde , f,从 cd 中删除关系 - 可能还有一个列指示操作时间以及它是否是 INSERT/UPDATE/删除。

如果它还不存在,我很乐意制作这样的脚本并分享它,但如果它存在,我不想重新发明轮子。如果没有,您认为其他人使用此类脚本最方便的格式是什么/您将如何将其融入您的模型开发工作流程?

最佳答案

我为自己创建了这个小怪物 php 脚本,它从一些速记 txt 文件生成 SQL DDL,现在它可以生成历史表及其 CREATE TRIGGER 语句。

http://simpleddl.coolpage.biz/

示例来源:

// ZZZ means "Create History Table + Triggers"
// you can try editing it live at the link above

!DROP
= ID id P AI

person ZZZ
  ID
  name _
  N mother_id -> person
  N father_id -> person
  !FK mother_id, father_id -> family

family ZZZ
  P female_id -> person
  P male_id   -> person

生成的 SQL DDL:

DROP   TABLE IF     EXISTS person;
CREATE TABLE IF NOT EXISTS person (
   id         INT NOT NULL AUTO_INCREMENT,
   name       VARCHAR(255) NOT NULL,
   mother_id  INT NULL,
   father_id  INT NULL,
   PRIMARY KEY ( id ),
   FOREIGN KEY ( mother_id ) REFERENCES person( id ),
   FOREIGN KEY ( father_id ) REFERENCES person( id ),
   FOREIGN KEY ( mother_id, father_id ) REFERENCES family( female_id, male_id )
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

DROP   TABLE IF     EXISTS family;
CREATE TABLE IF NOT EXISTS family (
   female_id  INT NOT NULL,
   male_id    INT NOT NULL,
   PRIMARY KEY ( female_id, male_id ),
   FOREIGN KEY ( female_id ) REFERENCES person( id ),
   FOREIGN KEY ( male_id ) REFERENCES person( id )
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP   TABLE IF     EXISTS zz_person;
CREATE TABLE IF NOT EXISTS zz_person (
   id         INT NOT NULL,
   name       VARCHAR(255) NOT NULL,
   mother_id  INT NULL,
   father_id  INT NULL,
   _zz_id     INT NOT NULL AUTO_INCREMENT,
   _zz_op     CHAR(1) NOT NULL,
   _zz_date   datetime NOT NULL,
   PRIMARY KEY ( _zz_id ),
   INDEX P ( id ),
   INDEX ( father_id, mother_id ),
   INDEX ( _zz_op ),
   INDEX ( _zz_date )
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

DROP   TABLE IF     EXISTS zz_family;
CREATE TABLE IF NOT EXISTS zz_family (
   female_id  INT NOT NULL,
   male_id    INT NOT NULL,
   _zz_id     INT NOT NULL AUTO_INCREMENT,
   _zz_op     CHAR(1) NOT NULL,
   _zz_date   datetime NOT NULL,
   PRIMARY KEY ( _zz_id ),
   INDEX P ( male_id, female_id ),
   INDEX ( _zz_op ),
   INDEX ( _zz_date )
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;


DROP   TRIGGER IF EXISTS INSERT_ON_person;
CREATE TRIGGER           INSERT_ON_person
                   AFTER INSERT ON person
FOR EACH ROW INSERT INTO
zz_person (     id,     name,     mother_id,     father_id, _zz_date, _zz_op )
   VALUES ( NEW.id, NEW.name, NEW.mother_id, NEW.father_id,  NOW()  ,  'i'   );

DROP   TRIGGER IF EXISTS UPDATE_ON_person;
CREATE TRIGGER           UPDATE_ON_person
                   AFTER UPDATE ON person
FOR EACH ROW INSERT INTO
zz_person (     id,     name,     mother_id,     father_id, _zz_date, _zz_op )
   VALUES ( NEW.id, NEW.name, NEW.mother_id, NEW.father_id,  NOW()  ,  'u'   );

DROP   TRIGGER IF EXISTS DELETE_ON_person;
CREATE TRIGGER           DELETE_ON_person
                   AFTER DELETE ON person
FOR EACH ROW INSERT INTO
zz_person (     id,     name,     mother_id,     father_id, _zz_date, _zz_op )
   VALUES ( OLD.id, OLD.name, OLD.mother_id, OLD.father_id,  NOW()  ,  'd'   );

DROP   TRIGGER IF EXISTS INSERT_ON_family;
CREATE TRIGGER           INSERT_ON_family
                   AFTER INSERT ON family
FOR EACH ROW INSERT INTO
zz_family (     female_id,     male_id, _zz_date, _zz_op )
   VALUES ( NEW.female_id, NEW.male_id,  NOW()  ,  'i'   );

DROP   TRIGGER IF EXISTS UPDATE_ON_family;
CREATE TRIGGER           UPDATE_ON_family
                   AFTER UPDATE ON family
FOR EACH ROW INSERT INTO
zz_family (     female_id,     male_id, _zz_date, _zz_op )
   VALUES ( NEW.female_id, NEW.male_id,  NOW()  ,  'u'   );

DROP   TRIGGER IF EXISTS DELETE_ON_family;
CREATE TRIGGER           DELETE_ON_family
                   AFTER DELETE ON family
FOR EACH ROW INSERT INTO
zz_family (     female_id,     male_id, _zz_date, _zz_op )
   VALUES ( OLD.female_id, OLD.male_id,  NOW()  ,  'd'   );

测试 fiddle :

http://sqlfiddle.com/#!2/d05e6/1

关于mysql - 加速或自动创建历史表触发器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15019971/

有关mysql - 加速或自动创建历史表触发器的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  6. ruby - 如何使用 RSpec::Core::RakeTask 创建 RSpec Rake 任务? - 2

    如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake

  7. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  8. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  9. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  10. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

随机推荐