PostgreSQLのエラー『relation does not exist』の解決方法

PostgreSQLのエラー『relation does not exist』の解決方法

このエラーは、SQL文内で指定したテーブルやビューなどのリレーションが存在しない、またはアクセスできないときに発生する。特にスキーマ名の指定忘れや、テーブル作成前のクエリ実行、権限不足などで頻出する。エラーの発生条件を踏まえ、考えられる原因とその対応方法を詳しく整理する。

エラーメッセージの例と発生条件

ERROR:  relation "users" does not exist
LINE 1: SELECT * FROM users;
^

このエラーは、PostgreSQLがSQL文中の「users」というリレーション(テーブルやビューなど)を見つけられなかったときに表示される。

原因1: 対象のテーブルが存在していない

-- テーブルが未作成
SELECT * FROM users;

解決策1: 対象のテーブルが存在するか確認する

-- テーブル一覧を確認
\d
-- 指定テーブルの存在確認
\d users

原因2: スキーマ名を指定していない

-- テーブルが"public"以外のスキーマにある
SELECT * FROM users;

解決策2: スキーマ名を明示的に記述する

-- 正しい例(スキーマ指定)
SELECT * FROM my_schema.users;

原因3: 大文字や特殊文字を使ったテーブル名を引用符なしで指定している

-- 作成時にダブルクォート付き
CREATE TABLE "Users" (id SERIAL PRIMARY KEY);

-- 誤った呼び出し(小文字として扱われる)
SELECT * FROM Users;

解決策3: 大文字や特殊文字を含む名前にはダブルクォートを使用

-- 正しい呼び出し
SELECT * FROM "Users";

原因4: マイグレーションが正しく適用されていない

マイグレーションツール(Rails, Django, Flywayなど)でテーブル作成前にクエリを実行している。

解決策4: マイグレーションが完了していることを確認

マイグレーションの順序を見直し、テーブル作成後に参照クエリが実行されているかを確認する。

原因5: 一時テーブル(TEMP)のスコープ外アクセス

-- 一時テーブルを作成
CREATE TEMP TABLE temp_data (id INT);

-- 他のセッションやトランザクションで参照
SELECT * FROM temp_data; -- 存在しない扱いになる

解決策5: TEMP TABLEは同一セッション内でのみ使用する

一時テーブルは作成したセッション内でのみ参照可能なため、別セッションでは使用できない。

原因6: データベース接続時のsearch_pathの設定不足

-- クエリではスキーマ指定なし
SELECT * FROM users;

だが、search_path に “users” のあるスキーマが含まれていない。

解決策6: search_path を明示的に設定

-- 現在のsearch_path確認
SHOW search_path;

-- 必要に応じて設定
SET search_path TO my_schema, public;

原因7: テーブル作成直後に別接続から参照している

トランザクションがコミットされていないため、他のセッションからテーブルが見えない。

解決策7: COMMITを忘れずに行う

BEGIN;
CREATE TABLE users (id SERIAL PRIMARY KEY);
COMMIT; -- ←これがないと他セッションからは見えない

原因8: DROP TABLE文が先に実行されている

-- テーブル削除済み
DROP TABLE users;

-- その後で参照
SELECT * FROM users;

解決策8: テーブルの存在チェックを行う

-- 事前チェック
SELECT to_regclass('public.users'); -- テーブルがあれば名前、なければNULLを返す

原因9: マテリアライズドビューや通常ビューの依存テーブルが消失している

ビュー作成後に依存するテーブルが削除されている。

解決策9: ビューの依存関係を確認する

-- ビューの定義を確認
\d+ my_view
-- または
SELECT * FROM pg_depend WHERE objid = 'my_view'::regclass;

原因10: 権限不足でテーブルが見えていない

テーブルは存在しているが、該当ユーザーにSELECT権限がないときにも同様のエラーになることがある。

解決策10: アクセス権を確認し、必要に応じてGRANT

-- 権限確認
\z users

-- 必要なら付与
GRANT SELECT ON users TO my_user;

まとめ

『relation does not exist』エラーは単純なスペルミスからスキーマの指定漏れ、セッションスコープ、マイグレーション漏れ、権限設定ミスなど様々な原因で発生する。エラーメッセージだけでは本質的な原因が掴みにくいため、search_pathの確認やテーブル一覧の確認、セッションの切り分けなどを通じて根本原因を丁寧に突き止めることが重要。