新規登録をしようとしたら、以下エラーが返ってきた。
それについて調べたので、メモ。
エラーメッセージ
Unique violation: 7 ERROR: duplicate key value violates unique constraint "TableName_pkey"↵DETAIL: Key (id)=(33) already exists. (SQL: insert into ~~(以下省略)
解決方法 & 実行履歴
PostgreSQLでINSERT時に自動採番の主キーが重複してエラーが出る場合の対処法 で紹介されている方法で解決した。
ただ、Postgresの使い方や実行した結果等を記録として残したいので、記述します。
PastgreSQLにログイン
# まずはhomesteadにログイン
$homestaed ssh
# PostgreSQLにログイン
vagrant@homestead:~$ psql -d DATABASE -U homestead -h 127.0.0.1
接続情報はプロジェクトの
.env
ファイルに記載されている。
.env
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=database_name
DB_USERNAME=homestead
DB_PASSWORD=*****
### 参考サイトの実行結果
参考:[PostgreSQLコマンドチートシート](https://qiita.com/Shitimi_613/items/bcd6a7f4134e6a8f0621)
```sql
# tableのレコード数を確認
database=# select MAX(id) FROM table_name;
max
-----
40
(1 row)
# シーケンスの番号を確認
# レコード数よりも小さいことが確認出来ました。
database=# select nextval('table_name_id_seq');
nextval
---------
34
(1 row)
#シーケンス番号をレコード数に合わせる
database=# select setval('table_name_id_seq', (select max(id) from table_name));
setval
--------
40
(1 row)
# シーケンスの番号を再確認
# レコード番号以上になっている事が確認出来ました。
database=# select nextval('table_name_id_seq');
nextval
---------
41
(1 row)
これで、新規登録が出来ました。
しかし、採番されたのが42番。41番が欠番になってしまった。
もう一度登録してみると、43番となったので問題は解決したようだが、気持ち悪い。。。
「とりあえず、解決したから、もう良い」と言う場合
PostgreSQLを終了する
database=# \q
シーケンスってなに?
シーケンスオブジェクト(シーケンス生成器とも単にシーケンスとも呼ばれます)とは CREATE SEQUENCE コマンドで作成される 1 行の特別なテーブルです。シーケンスオブジェクトは通常テーブルの行に一意の識別子を生成するために使用されます。
引用:6.11. シーケンス操作関数 - PostgreSQL 7.3.4 ユーザガイド
上記サイトを見ると、以下記載もあった。
nextval
シーケンスオブジェクトをその次の値に進めその値を返します。これは自動的に処理されます。 複数のセッションが同時に nextval を実行したとしても、それぞれの工程は個別のシーケンス値を間違いなく受け取ります。
引用:6.11. シーケンス操作関数 - PostgreSQL 7.3.4 ユーザガイド
つまり、先ほどの最後に、select nextval('table_name_id_seq');
をしたから、シーケンス番号が41番に進んでしまって、新規登録時42番が採番されてしまったのだった。
やはりコマンドは必ず一度調べてから実行すべきですね。
なぜシーケンス番号がヅレるの?
SQLでinsertして行く分には基本問題ないけれど、CSVなどからインポートした場合、保存した値とずれてしまい、(以降省略)
引用:地方で活動するweb制作者の日々を綴るblog
なるほど!
確かに該当のDLは、開発用のでもデータを流し込んで作った。
まとめ
今までMySQLばかりを触っていたため、PostgreSQLを使ってこなかった。
そのため、今回PostgreSQLの操作方法やシーケンスオブジェクトと言うものを使っている事が知れたことは良かった。
今後もPostgreSQLとはお付き合いしていくと思うので、もっと仲良くなっていきたいなと思った今日この頃でした。