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

はじめに

これは、PostgreSQL Advent Calendar 2025の7日目の記事になります。

社内開発したレプリケーションツールがありまして、PostgreSQLから SQLServerにデータをコピーしています。レプリケーションは、データ保持の観点もありますが、SQLServerのBIツールで見える化やデータ分析に使います。

仕組み的にはレプリケーションしたいテーブルにトリガーを張って、専用のレプリケーション用テーブルに 実行したSQLをセット、定期実行でSQLServerから PostgreSQLのレプリケーション用テーブルを参照して、SQLを実行します。

今回、レプリケーション先をSQLServerからPostgreSQLにする改善がありました。つまり、PostgreSQLからPostgreSQLですね。

でも、それなら PostgreSQLの標準機能である論理レプリケーションが使えるじゃないですか?
一応、提案してみたのですが、レプリケーションの残数が分かる、何かあった時にコントロールしやすいということで、社内開発したレプリケーションツールを採用となりました。

本題

レプリケーションしたいテーブルの型を調べると、SERIAL型がありました。SERIAL型とは、自動的に連番を生成するデータ型です。
幾つか疑問が湧いてきます。

  • SERIAL型に任意の値をセットできるのか?
  • レプリケーション先もSERIAL型では値はどうなる?
  • レプリケーション先のSERIAL型は別の型にするべきか?

まー試せば分かるよね。

検証

シーケンス有りのテーブルを作成する。

CREATE TABLE items (
    id SERIAL PRIMARY KEY,
    name text
);

通常にデータをセット

INSERT INTO items (name) VALUES ('AAA');
INSERT INTO items (name) VALUES ('BBB');

SELECT * FROM items;
SELECT last_value FROM items_id_seq;
id name
1 AAA
2 BBB

シーケンスの値は 2 です。

last_value
2

シーケンスに任意の値をセット

INSERT INTO items (id, name) VALUES (100, 'CCC');

SELECT * FROM items;
SELECT last_value FROM items_id_seq;
id name
1 AAA
2 BBB
100 CCC

シーケンスの値は 2 のままで更新されません。
※自動追随はしないってこと。

last_value
2

注意

シーケンスの値は更新されないので、シーケンス値 100 で既に入っていたら、当然エラーになります。

ERROR: duplicate key value violates unique constraint "items_pkey"ERROR: duplicate key value violates unique constraint "items_pkey"

その場合、シーケンスを追いつかせる。

SELECT setval('items_id_seq', (SELECT MAX(id) FROM items));

または

SELECT setval('items_id_seq', 100, true);

まとめ

動作 結果
SERIAL カラムに任意の値を INSERT そのまま入る(エラーなし)
シーケンスは追随する? しない
次の INSERT がどうなる? シーケンス値が既存 ID と衝突→エラーの可能性
正しい修正方法 setval() でシーケンスを調整

その他のDB

ChatGPT調べになります。
SQLServerは、特別に許可する必要があるが、他はPostgreSQLと似た動作になりますね。

DB 任意の値 INSERT 設定が必要? 自動追随 備考
PostgreSQL ⭕ 入る 不要 ❌ しない SERIAL/IDENTITYとも
MySQL ⭕ 入る 不要 ⭕ 条件付きで追随 挙動が最も柔軟
SQL Server ⭕ だがデフォルト禁止 IDENTITY_INSERT ON 必須 ❌ 手動 厳格
Oracle(SEQUENCE) ⭕ 入る 不要 ❌ しない トリガー次第
Oracle(IDENTITY) ⭕ だがデフォルト禁止 設定次第 ❌ 手動 SQL Server と同じ明示 INSERT を禁止するか許可するか選べる
SQLite ⭕ 入る 不要 ❌ しない AUTOINCREMENT は特殊

最後に

レプリケーションする上では、SERIAL型に任意の値をセットすればいいし、レプリケーション先の型を変更する必要もありません。

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?