2019-11-24 00:23:39
【elixir】ecto でpostgresqlにinsertしたら"constraint error when attempting to insert struct:"エラーが出た
目次
- 症状
- 原因
- 対応
症状
最近、ブログに記事投稿機能を追加しました。しかし、投稿画面から投稿する際に以下のエラーが発生しました。
constraint error when attempting to insert struct:
* blogs_pkey (unique_constraint)
If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `unique_constraint/3` on your changeset with the constraint
`:name` as an option.
The changeset defined the following constraints:
* blogs_url_title_key (unique_constraint)
* PRIMARY (unique_constraint)
原因
自動採番されるIDカラムの値を含めたinsertを手動実行していたことが原因でした。本番データに同期したさいに本番DBからエクスポートしたデータを手動実行していました。SQLにはIDカラムの値も含まれています。
postgresの自動採番を確認するとIDカラムの値 nextval がズレていることが確認できました。
シーケンス一覧を表示。
nao000dotcom=# SELECT c.relname FROM pg_class c LEFT join pg_user u ON c.relowner = u.usesysid WHERE c.relkind = 'S';
relname
-----------------------
blogcategories_id_seq
blogs_id_seq
(2 rows)
今回起きたエラーは blogs_id_seq の値のズレでした。 next_val の値を確認します。
nao000dotcom=# select * from blogs_id_seq;
last_value | log_cnt | is_called
------------+---------+-----------
22 | 32 | t
(1 row)
last_value の値が自動採番の最後の値を示します。この状態でテーブルにIDカラムの値に23を指定してinsertしていました。再び next_val の値を確認すると先程と変わりありません。
nao000dotcom=# select * from blogs_id_seq;
last_value | log_cnt | is_called
------------+---------+-----------
22 | 32 | t
(1 row)
この状態で記事投稿画面から投稿するとエラーが発生します。投稿画面からの投稿にはID値を含めていません。
対応
last_valueを再設定する以下のSQLを実行します。手動追加した分のID値を設定します。
select setval ('blogs_id_seq', 23);
これで投稿画面からの投稿でエラーがでなくなりました。普通のことかもしれないですが、個人的に沼でした。ググっても出てこなかったので。