1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PostgreSQL】Serial型の自動採番を経ずにデータ投入した際、次回以降のINSERTで一意制約違反になるのを回避する

Posted at

概要

Serial型カラムを持つテーブルにCSVインポートなどで直接データを投入した場合、シーケンス値が更新されず、次回のINSERT時に一意制約違反が発生します。そこで、次回の採番を既存データのMAX値 + 1の値からスタートするよう変更して、次回以降のINSERT処理で一意制約違反が起こらないようにします。

項目 内容
取り扱う内容 • Serial型カラムを持つテーブルへの直接データ投入時の問題と解決方法
想定読者 • CSVインポートやデータ移行作業を行う人
• Serial型カラムを含むテーブルを管理・利用する人
• データインポート後の一意制約違反で困っている人
ゴール • データ投入後のシーケンス値の不整合を理解できる
• 一意制約違反を未然に防ぐための対処方法を習得できる

Serialの自動採番を経ずにデータ投入した場合、Serial型の持っている連番のシーケンスは自動更新されない

以下のケースでは、Serial型の持っている連番のシーケンスは自動更新されません。

  • CSVファイルからデータインポートした場合
  • Serial型の列にsql文で直接、値を指定してinsertした場合

このまま新規データをinsertすると、CSVに存在した値を無視して採番処理され、ユニーク制約に違反する場合があります。

例:

  1. createしたばかりのテーブルにおいて、Serial型として定義したid列の次回採番は1
  2. ここへidが100まで登録済のCSVをインポートした場合でも、id列の次回採番値は1のまま、変更されない
  3. 次回新規レコードがinsertされる時のidは101となってほしいが、2のために、実際には1が採番される
  4. 結果として、id列にユニーク制約がある場合、制約違反となってinsertエラーとなる

次回の採番を既存データのMAX値 + 1の値からスタートするよう変更する

-- <>内の値はテーブル定義に応じて変更のこと
SELECT setval('<tablename>_id_seq', (SELECT MAX(<Serial型の列名>) FROM 
<tablename>));

テーブルに対応するシーケンスの値を見ると、既存値のMAX値で最大の値が更新されています。次回insert時は、この値に1を加算した値で採番されるので、一意制約違反は発生しません。
image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?