はじめに
これは、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型に任意の値をセットすればいいし、レプリケーション先の型を変更する必要もありません。