Postgresqlのシーケンス番号

PostgresqlのDBで、レコードをインサートしようとしたところエラーが出たので原因を調査したメモ。

エラー内容

エラーは以下のような内容。

duplicate key value violates unique constraint “table_pkey”

table_pkeyは、テーブル名+pkeyとなる。
文字通り受け取るなら、ユニークでないといけない項目が被ってるよ、というもの。

しかし投げたレコードは特に被っている項目もなく、ユニークな項目もIDだけだった。

原因

値をシークエンスに設定したint型の項目は、インサートした順番に自動発番してくれるのだが、その発番する番号はシーケンス番号、として内部的に保持しているよう。 それが、内容を別DBからコピーなどすると上手く更新されない事があるらしい。たぶん。

シーケンス番号

確認

現在のシーケンス番号が何番になっているかを確認するためには以下のSQLを発行してやるとよい。

1
SELECT last_value FROM シーケンス名

シーケンス名は、デフォルトでは、テーブル名_項目名_seqとなっていると思われる。 Posticoで確認する場合は、Navigate -> Go to Terminalでターミナルが開くので、そこでSQLを発行して確認する事が出来る。

今回発行してみると、9が返ってきた。

しかし実際のレコードは12まであり、保持されているシーケンス番号の次の番号から発番されるため、10が発番され重複エラーとなっていたよう。

設定

なので、このシーケンス番号を設定し直してやる。
シーケンス番号を設定するには以下。

1
SELECT setval('シーケンス名', 数値); 

シーケンス番号はさきほどと同じ。数値はここでは12を設定してやる。

Posticoで実行すると以下のようになる。

これで12にセットされたため、インサートを実行すると13から発番されるので重複エラーが解消された。

参考

   このエントリーをはてなブックマークに追加