NB Jogger's blog

NBが好きなのです

【Perl】DBIx::Classを使ったテーブルの採番

2012-11-24 23:06:44 | プログラム
テーブルのIDを採番する際、通常はAUTO_INCREMENTを使うと思いますが、
レコード数・増数が多く、DBのShardingが求められる場合、AUTO_INCREMENTは使えません。
そのため、IDを払い出す採番用のテーブルを用意し、レコード追加時のIDを管理します。

まず準備としてテーブルを作成し、IDを数え上げるためのレコードを1行だけ追加します。

# テーブルの作成
CREATE TABLE `id_pot` (
  `id` bigint(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# IDを数え上げるためのレコードを1行だけ追加
INSERT INTO id_pot SET id = 0;


この採番用テーブルをDBIから利用する場合は下記のようなコードになります。

my $dbh = DBI->connect(
    'dbi:mysql:database', 'user', '',
);
my $sth = $dbh->prepare(
    'UPDATE id_pot SET id = LAST_INSERT_ID(id + 1)'
);
$sth->execute();
print $sth->{mysql_insertid}; ## 1が出力される

最近のアプリケーションだと上のようにDBIで生のクエリを扱うことはまれで、
DBIx::ClassなどのORMを使うことが多いでしょう。
DBIx::Class利用して先ほどと同じことをする場合は以下のようになります。

use strict;
use warnings;
use DBIx::Class::Schema::Loader;

my $schema = DBIx::Class::Schema::Loader->connect(
    'dbi:mysql:database', 'user', '',
);

my $resultset = $schema->resultset('IdPot');
$resultset->search->update({
    id => \'LAST_INSERT_ID(id + 1)',
});
print $schema->storage->last_insert_id; ## 1が出力される


個人的に詰まったのは
  • SET id = id + 1 のインクリメントを行うSQL文のDBIx::Classでの実行
  • LASET_INSERT_IDの取得
でした。

ここの肝は下記の部分です。

$resultset->search->update({
    id => \'LAST_INSERT_ID(id + 1)',
});
$schema->storage->last_insert_id;

コメントを投稿