How do you manage triggers in RDBMS.
RDBMSレベルのtriggerはアプリケーションレベルのトリガーにくらべてもれもなく、安心感があってよいものですね。
しかし一方で、RDBMS レベルのtriggerは、deploy がむずかしいという問題もあります。
わたくしは、以下のようなスクリプトをつかって、スキーマと実際のDBの様子をつきあわせて、ちがっていれば DROP して CREATE しなおすというようなスクリプトをかいています。
みなさんはどのように管理していますか?
#!/usr/bin/env perl use strict; use warnings; use utf8; use 5.10.0; use autodie; use Log::Minimal; use File::Spec; use Data::Dumper; ... my $dbh = $dbh; my %db_triggers = map { $_->{Trigger} => $_ } @{$dbh->selectall_arrayref(q{show triggers}, +{Slice => {}})}; my %triggers = parse_trigger_sql(File::Spec->catfile($c->base_dir, q{sql/trigger.sql})); while (my ($name, $attr) = each %triggers) { if (need_install($db_triggers{$name}->{Statement}, $attr->{sql})) { say qq{-- $attr->{name}\@$attr->{table} --}; say qq{LOCK TABLES $attr->{table} WRITE;}; say qq{DROP TRIGGER IF EXISTS $attr->{name};}; say qq{DELIMITER |}; say qq{$attr->{header}}; say qq{$attr->{sql}}; say qq{|}; say qq{DELIMITER ;}; say qq{UNLOCK TABLES;}; say qq{}; } } exit; # print trigger source my $trigger_file = File::Spec->catfile($c->base_dir, 'sql/trigger.sql'); open my $fh, '<', $trigger_file; print $_ while <$fh>; close $fh; sub need_install { my ($dbt, $srct) = @_; return 1 unless $dbt; $dbt =~ s/"\n"/"\\n"/g; $dbt =~ s/"\r"/"\\r"/g; $dbt =~ s/\n/ /g; $dbt =~ s/\s{2,}/ /g; $dbt =~ s/\s+$//g; $srct =~ s/\n/ /g; $srct =~ s/\s+$//g; if ($dbt ne $srct) { debugf("db : %s", ddf($dbt)); debugf("src: %s", ddf($srct)); return 1; } else { return 0; } } sub parse_trigger_sql { my ($src) = shift; open my $fh, '<', $src or die "Cannot open file: $src"; my $delimiter = 'eMpTy'x10; my $sql; my %triggers; my $name; while (<$fh>) { s/--.+//; s/^\s+//; s/\s{2,}/ /g; next unless /\S/; given ($_) { when (/^DELIMITER\s+(.)$/) { $delimiter = quotemeta $1; } when (/^$delimiter/) { $triggers{$name}->{sql} = $sql; undef $sql; } when (/(?<header>CREATE TRIGGER (?<name>\S+) (?<before_after>\S+) (?<command>\S+) ON (?<table>\S+) FOR EACH ROW) BEGIN/) { $name = $+{name}; $triggers{$name} = {%+}; $sql = "BEGIN\n"; } default { $sql .= $_; } } } close $fh; return %triggers; }