0
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の外部テーブル(FDW)で「列が存在しません」「リレーションが存在しません」エラーにハマった話

0
Posted at

概要

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. まとめ

外部テーブルを利用する際は、以下の「同期」が重要です。

  1. 構造の同期: ローカル側の FOREIGN TABLE 定義と、リモート側の ACTUAL TABLE 構造を一致させる。
  2. 依存オブジェクトの配置: デフォルト値や関数で参照するオブジェクト(ビューやシーケンス)は、リモート側にも適切に配置・公開されている必要がある。
0
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
0
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?