概要
Serial型カラムを持つテーブルにCSVインポートなどで直接データを投入した場合、シーケンス値が更新されず、次回のINSERT時に一意制約違反が発生します。そこで、次回の採番を既存データのMAX値 + 1
の値からスタートするよう変更して、次回以降のINSERT処理で一意制約違反が起こらないようにします。
項目 | 内容 |
---|---|
取り扱う内容 | • Serial型カラムを持つテーブルへの直接データ投入時の問題と解決方法 |
想定読者 | • CSVインポートやデータ移行作業を行う人 • Serial型カラムを含むテーブルを管理・利用する人 • データインポート後の一意制約違反で困っている人 |
ゴール | • データ投入後のシーケンス値の不整合を理解できる • 一意制約違反を未然に防ぐための対処方法を習得できる |
Serialの自動採番を経ずにデータ投入した場合、Serial型の持っている連番のシーケンスは自動更新されない
以下のケースでは、Serial型の持っている連番のシーケンスは自動更新されません。
- CSVファイルからデータインポートした場合
- Serial型の列にsql文で直接、値を指定してinsertした場合
このまま新規データをinsertすると、CSVに存在した値を無視して採番処理され、ユニーク制約に違反する場合があります。
例:
- createしたばかりのテーブルにおいて、Serial型として定義した
id
列の次回採番は1 - ここへ
id
が100まで登録済のCSVをインポートした場合でも、id
列の次回採番値は1のまま、変更されない - 次回新規レコードがinsertされる時の
id
は101となってほしいが、2のために、実際には1が採番される - 結果として、
id
列にユニーク制約がある場合、制約違反となってinsertエラーとなる
次回の採番を既存データのMAX値 + 1
の値からスタートするよう変更する
-- <>内の値はテーブル定義に応じて変更のこと
SELECT setval('<tablename>_id_seq', (SELECT MAX(<Serial型の列名>) FROM
<tablename>));
テーブルに対応するシーケンスの値を見ると、既存値のMAX値で最大の値
が更新されています。次回insert時は、この値に1を加算した値で採番されるので、一意制約違反は発生しません。