Ruby Sequel Oracle Sequence Literal
INSERT文を実行する場合にOracleのSequenceを利用してプライマリキーを自動でインクリメントしていくようなパターンのときに、なぜかリテラルがうまいこと動かなかったのでメモ。
シーケンスを取得する際に、次の通りbindを使って文字列として設定してしまうと、バインド変数使用時の ORA-01722 エラーが発生します
DB[:items].insert(:a => 1, :b => "user_seq.nextval") # INSERT INTO items (a, b) VALUES ("1", "user_seq.nextval")
また、Sequel::Dataset クラスにある literal を使っても、同様にORA-01722 エラーが発生します
DB[:items].insert(:a => 1, :b => DB[:items].literal('users_seq.nextval')) # INSERT INTO items (a, b) VALUES ("1", '"user_seq"."nextval"')
そこで、リテラルには、シンボルを使ってデータ型で対応します
その際、シーケンス名と次の値を取得する nextval の間を __ (アンダースコアx2)で繋げます
DB[:items].insert(:a => 1, :b => :users_seq__nextval) # INSERT INTO items (a, b) VALUES ("1", "user_seq"."nextval")
"user_seq"."nextval"のような形にすることで、Oracleが代入時に実行する暗黙変換がうまいこと比較されます。