概要
PostgreSQLの外部データラッパ(postgres_fdw)を使用して、別サーバのテーブルをローカル環境のように操作しようとした際、定義上は問題ないはずなのに「カラムがない」「シーケンスが見つからない」というエラーに直面しました。その原因と解決策をまとめます。
1. 発生した問題
外部テーブルを作成し、GUIツールやLaravelからアクセスしたところ、以下の2つのエラーが発生しました。
-
現象①:
SELECT時に列 "カラム名" は存在しませんと言われる。(information_schemaには存在するのに実行不可) -
現象②: Laravelでの保存時(INSERT時)に
ERROR: リレーション "public.v_doctors_id_seq" は存在しませんというエラーで失敗する。
2. 原因の切り分け
外部テーブル(Foreign Table)は、あくまでリモートサーバへの窓口です。
-
現象①の原因: ローカル側の
CREATE FOREIGN TABLEでカラムを追加しても、リモート側の実テーブルにそのカラムが存在しない場合、クエリ転送時にリモート側でエラーになります。 -
現象②の原因:
idのデフォルト値として外部テーブル(ビュー)を参照する関数を設定していましたが、その参照先のビューがリモート側に存在していなかったため、ID取得時に失敗していました。
3. 解決策
ステップ1:リモート側へのカラム追加
まず、リモートサーバ側のテーブルに不足していたカラムを追加します。
- リモート側で実行
ALTER TABLE doctors ADD COLUMN is_new_entry boolean DEFAULT true;
ステップ2:リモート側への採番用ビュー作成
ローカル側の関数がIDを取得できるように、リモート側でシーケンス値を返すビューを作成します。
- リモート側で実行
CREATE VIEW v_doctors_id_seq ASSELECT nextval('doctors_id_seq') as seq_val;
これにより、ローカル側の関数 f_doctors_id_seq() が外部テーブル経由でこのビューを叩き、正しく nextval を取得できるようになりました。
4. まとめ
外部テーブルを利用する際は、以下の「同期」が重要です。
-
構造の同期: ローカル側の
FOREIGN TABLE定義と、リモート側のACTUAL TABLE構造を一致させる。 - 依存オブジェクトの配置: デフォルト値や関数で参照するオブジェクト(ビューやシーケンス)は、リモート側にも適切に配置・公開されている必要がある。