November 16, 2005
最近、SQL で
例えば、住所録を作ろうなんつって、テーブルを組みたいわけだが、そもそも WHERE 句に入る要素なんて名前ぐらいしかないなぁ…という場合は
要するに、
んで、この
よく Data::Dumper とかで、文字列化した値を入れておいて、それを
なんとか楽に出来んかなーっていっつも思ってたりしたんですが、今日いつものように CPAN あたりを徘徊していたら、Class::DBI::Plugin::PseudoColumns とかいう、何やらそれにうってつけなモジュールがあった。
取り出す時もいつも通り、
携帯番号でも登録しようかなーって時に「あー、そういや TANAKA は携帯電話を 2 個持ってたなー」とか思い出す。でもそんな取るに足らないデータなのに「一対多だから」という理由で正規化するのもアホくさい。
いやー、なかなか素敵。
てことで、お手軽に擬似的カラムを扱える、Class::DBI::Plugin::PseudoColumns は、軽くオススメです。
WHERE 句に入らず、ORDER BY やら GROUP BY もされず、かつ MAX() だとか MIN() だとかを求められる必要もない、言うなれば「取るに足らない値」とかを、個別のカラムに持たず、そういうのを一気にまとめて text 型のカラムに入れたりすることがあったりする。例えば、住所録を作ろうなんつって、テーブルを組みたいわけだが、そもそも WHERE 句に入る要素なんて名前ぐらいしかないなぁ…という場合は
CREATE table address ( id int unsigned NOT NULL auto_increment, name varchar(255) NOT NULL default '', props text, PRIMARY KEY (id), KEY (name) );こんなようなテーブルを一個作っておいたりして。
要するに、
name 以外の値は「取るに足らない値」で、props というカラムが一個あるだけ。んで、この
propsに郵便番号だ、住所だ、電話番号をつっこむわけです。mysql> INSERT INTO address (name)
VALUES ('YAMADA'), ('SUZUKI'), ('TANAKA');
こんなんだったとすると、Class::DBI で扱う場合、いつものようにこのテーブルのクラスを作るわけですが、props のカラムを扱うのが難しい。よく Data::Dumper とかで、文字列化した値を入れておいて、それを
eval() して取り出したりするんですが、その手続きが意外に面倒臭かったり。なんとか楽に出来んかなーっていっつも思ってたりしたんですが、今日いつものように CPAN あたりを徘徊していたら、Class::DBI::Plugin::PseudoColumns とかいう、何やらそれにうってつけなモジュールがあった。
package MyData::Address;
use strict;
use base qw(MyData::Base);
use Class::DBI::Plugin::PseudoColumns;
__PACKAGE__->table('address');
__PACKAGE__->columns(Primary => qw(id));
__PACKAGE__->columns(All => qw(id name props));
__PACKAGE__->pseudo_columns(props => qw(zipcode address sex phone cellphone));
1;
とりあえず、今んとこ
mysql> SELECT * FROM address; +----+--------+-------+ | id | name | props | +----+--------+-------+ | 1 | YAMADA | NULL | | 2 | SUZUKI | NULL | | 3 | TANAKA | NULL | +----+--------+-------+ 3 rows in set (0.00 sec)こんなんなってますが「そういや、YAMADA も SUZUKI も TANAKA も男だったなー」とかいう時
use strict;
use MyData::Address;
my $iter = MyData::Address->retrieve_all;
while (my $row = $iter->next) {
$row->sex('M');
$row->update;
}
こんなカンジで、いつものように、普通のカラムを扱うようにいじってみると、
mysql> SELECT * FROM address;
+----+--------+----------------+
| id | name | props |
+----+--------+----------------+
| 1 | YAMADA | {'sex' => 'M'} |
| 2 | SUZUKI | {'sex' => 'M'} |
| 3 | TANAKA | {'sex' => 'M'} |
+----+--------+----------------+
3 rows in set (0.00 sec)
こんな風になります。取り出す時もいつも通り、
use strict; use MyData::Address; my $yamada = MyData::Address->retrieve(1); print $yamada->sex, "\n";お手軽に利用出来たりします。
携帯番号でも登録しようかなーって時に「あー、そういや TANAKA は携帯電話を 2 個持ってたなー」とか思い出す。でもそんな取るに足らないデータなのに「一対多だから」という理由で正規化するのもアホくさい。
use strict; use MyData::Address; my $tanaka = MyData::Address->retrieve(3); $tanaka->cellphone([qw(090-1234-56xx 090-2345-67xx)]); $tanaka->update;こうしておけば、
use strict; use Data::Dumper; use MyData::Address; my $tanaka = MyData::Address->retrieve(3); my $cellphones = $tanaka->cellphone; print Dumper $cellphones;こうした時に
$VAR1 = [
'090-1234-56xx',
'090-2345-67xx'
];
こう取り出せたりする。いやー、なかなか素敵。
てことで、お手軽に擬似的カラムを扱える、Class::DBI::Plugin::PseudoColumns は、軽くオススメです。