update_or_create method of DBIx::Class::ResultSet
DBIx::ClassでMySQLのREPLACEもしくは ON DUPLICATE KEY UPDATE に当たるものはなんなのか、前もわからなくていろいろ調べたのにまた今日も同じことを調べてたのでメモっとく。
my $recent = $self->{schema}->resultset('Recents')->update_or_create( {
id => $self->{user}->id,
....
} );
こう書く。一度newしてから
my $recent = $self->{schema}->resultset('Recents')->new( {
id => $self->{user}->id,
uniq_column => $self->{user}->accountname,
....
} );
$recent->update_or_create;
っていうのはできないので注意。
で、問題は生成されるSQLの質。
DBIx::Classの覚書 – Ktat’s Wiki に
$ENV{DBIC_TRACE} = 1;とすれば、STDERRに出力される。
と書いてあったのでこれで表示させた。すると update_or_create は
SELECT * FROM recents me WHERE ( ( me.id = '62' ) OR ( me.accountname = 'ku' ) )
UPDATE recents SET ............ WHERE ( id = '62' )
ふつうにSELECTしてUPDATEしてるの。しかも primary key 以外に unique index があるとORとったりしてる。まともなテーブルであればme.idでマッチしなくてme.accountnameでマッチするなんてあり得ない。これについては検索に使うキーを指定すれば解決。それも DBIx::Classの覚書 – Ktat’s Wiki に
update_or_create(\%arg)ユニークキー(プライマリーキー含む)で検索してくれる。
双方とも、第二引数に、{key => "uniq_index"}で、検索するユニークキー(プライマリーキーを含む)を指定することもできる。
とあるので第二引数を指定する。カラムの名前じゃなくてインデックスの名前を指定するところに注意。keyとして書くのはuniq_columnにUniq_indexという名前でユニークインデックスをはっていたらUniq_indexのほうを指定します。カラムの名前だと
DBIx::Class::ResultSet::update_or_create(): Unknown unique constraint nickname on 'uniq_column'
っていわれます。
こうするとめでたくSQLが
SELECT * FROM recents me WHERE ( ( me.accountname = 'ku' ) )
になります。プライマリキーをキーにしたいときはどうするか分かりませんでした。PRIMARYって書いたらNGだった。
ほとんど調べてないけど REPLACEとかON DUPLICATE KEY UPDATEしたかったらスクラッチでSQL書くとこまでフォールバックするしかないのかな….

No comments
Jump to comment form | comments rss [?] | trackback uri [?]