PostgreSQL の relation does not exist:原因と解決策
結論 relation "users" does not exist は、対象がこの世に無いという意味ではありません。指定した名前を、今の接続から解決できなかったという意味です。SQL の状態コードは 42P01、名称は undefined_table です。 relation はテーブルだけを指しません。公式ドキュメントは、pg_class がインデックス、シーケンス、ビュー、実体化ビューなども扱い、これらをまとめて relation と呼ぶと説明しています。 読み分けの起点は、文言の中に点があるかどうかです。スキーマ名を自分で書いた場合は relation "public.users" does not exist と点付きになり、書かなかった場合は relation "users" does not exist と名前だけになります。前者は指定したスキーマの中で見つからず、後者は検索経路をたどって見つからなかったという意味です。 そして、この文言は「無い」と「見えない」を区別しません。権限が足りずに検索経路から外れたスキーマも、存在しないスキーマも同じ結果です。 最初に確認すること 今の接続がどこを見ているかを確認します。 SELECT current_database(), current_user; SHOW search_path; 初期状態の検索経路は "$user", public です。先頭は利用者名と同じスキーマを指します。 次に、対象の所在を調べます。 SELECT n.nspname, c.relname, c.relkind FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = 'users'; 行が返らなければ、このデータベースには登録されていません。返るのに参照できないなら、スキーマか綴りの問題です。 原因別の確認方法と解決策 原因1:対象が検索経路に入っていないスキーマにある 上の照会で nspname が public 以外になっている場合です。修飾しない参照は検索経路を順にたどり、最初に一致したものを使います。経路に入っていないスキーマの中身は参照できません。 対処は、呼び出し側で修飾するか経路へ加えるかです。 SELECT * FROM app.users; SET search_path TO app, public; SET はそのセッションの間だけ有効です。毎回同じ状態にしたい場合は、ロールやデータベースへ既定値を設定します。 原因2:スキーマへの USAGE 権限が無い 同じクエリが、利用者を変えると成功する場合です。公式ドキュメントは、自分が所有していないスキーマの中身へ既定では触れられず、所有者が USAGE 権限を与える必要があると説明しています。 ...