【豆知識】「リレーションは存在しません」のエラーを解決したい
		PostgreSQLインサイド
	実現方法
FROM句にスキーマ名で修飾せずにテーブル名を指定して、SELECT文などのSQLを実行したときに、「リレーションは存在しません」(英語環境では「relation does not exist」)のエラーメッセージが出力されることがあります。これは、目的のテーブルが存在するスキーマが、スキーマ検索パス(search_path:検索対象となるスキーマのリスト)に設定されていないことが原因である可能性があります。
		このような場合、スキーマ検索パスの設定を確認し、対象となるスキーマが存在しない場合は追加してください。
実行例
前提
PostgreSQLでは、データベース作成時に「public」というスキーマがデフォルトで作成されます。自分のユーザー名と同じ名前のスキーマなど、別のスキーマを追加するには、CREATE SCHEMAコマンドで追加できます。
		下の図のように、データベース「test_db」にユーザー「user01」が所有するスキーマ「user01」が存在し、テーブル「product」が作成済みとなっているものとします。そして、テーブル「product」へのアクセス権を持つユーザー「user02」がスキーマ修飾(「スキーマ名.テーブル名」の形式)せずにFROM句にテーブル「product」を指定してSELECTコマンドを実行します。なお、「user01」および「user02」は共に「product」へのアクセス権を持つものとします。

PostgreSQLはスキーマ検索パスに設定されたスキーマ名を検索してテーブルを特定します。このとき、対象のテーブルが見つからないと、以下例のようなエラーが出力されます。
ERROR:  リレーション"product"は存在しません対処例
スキーマ検索パスの設定を確認し、対象となるスキーマが存在しない場合は追加します。ユーザー「user02」でtest_dbに接続して、以下のように操作します。
- 
				スキーマ検索パスの設定内容を確認 SHOWコマンドの使用例と出力例を下記に示します。 
test_db=> SHOW search_path;
   search_path
-----------------
 "$user", public
(1 行)"$user"とpublicが検索対象のスキーマであることが判ります。また、検索はスキーマ検索パスの先頭から順に実行されるので、このケース(デフォルト)では、"$user"、publicの順で検索されます。
		"$user"は現行ユーザーと同じ名前のスキーマ(この例ではuser02)を意味しますので、目的とするテーブル「product」が存在するスキーマ「user01」は、スキーマ検索パスに無いことがわかります。
		なお、SELECT文などで、存在しないスキーマがスキーマ検索パスに指定されていた場合、そのスキーマは無視され、次に指定されているスキーマが検索されます。
- 
				SETコマンドでスキーマ検索パスに「user01」を追加 ここでは、一般ユーザーでも現在のセッション中だけ設定を変更できる、SETコマンドの使用例を以下に示します。 
test_db=> SET search_path TO "$user", user01, public;この例では、現行ユーザーと同名のスキーマ(user02)、user01、publicの順で検索するよう指定しています。
		なお、もしスキーマ「user01」とスキーマ「public」に同じ名前のテーブルが存在した場合は、最初に検出されるテーブル、つまりスキーマ「user01」に属するテーブルが参照されます。
ポイント
- 
				エラーを解決するには、スキーマ検索パスの設定を変更する方法のほかに、テーブル名をスキーマ名で修飾して指定する方法もあります(例:user01.product)。アプリケーション開発の設計段階で、どちらの方法にするかの方針を決めておくことをお勧めします。 
- 
				スキーマ検索パスを設定するには、SETコマンド以外にも以下の方法があります。 - 
						設定ファイルpostgresql.confファイルのsearch_pathパラメーターに設定 データベースクラスタにアクセス可能なすべてのユーザーに対して、デフォルトのスキーマ検索パスとして永続的に設定されます。初期値では「"$user", public」が設定されています。変更する場合は、検索させたい順番でスキーマ名を記載します。 
 以下にスキーマ検索パスにスキーマ「user01」を追加する例を示します。search_path = "$user", user01, public変更後は、pg_ctlコマンドをreloadオプションで実行して設定ファイルを再読み込みし、変更を反映してください。 
- 
						ALTER ROLEコマンドで特定のユーザーに対して設定 特定のユーザーにおいて、デフォルトのスキーマ検索パスとして永続的に設定されます。 
 以下にユーザー「user02」のスキーマ検索パスにスキーマ「user01」を追加する例を示します。ALTER ROLE user02 SET search_path TO "$user", user01, public;
 
- 
						
- 
				スキーマが適用される仕組みは、SELECTコマンドによるテーブル参照時だけでなく、CREATE TABLEコマンドでテーブル作成先のスキーマを省略した場合にも適用されます。例えば、search_pathパラメーターのデフォルトの設定で以下のような操作をすると、public.t1のテーブルが作成されます。 CREATE TABLE t1(id int);- 
						備考PostgreSQL 15以降では、新しいデータベースが作成された時、データベース所有者とスーパーユーザーだけがデフォルトのpublicスキーマでオブジェクトを作成することができるよう変更されました。
 ¥dtコマンドでテーブル一覧を表示すると、以下例のように作成されていることが確認できます。 test_db=> ¥dt リレーション一覧 スキーマ | 名前 | タイプ | 所有者 ----------+------+----------+-------- public | t1 | テーブル | user03
- 
						
- 
				各データベースには、publicスキーマ、ユーザー作成のスキーマの他に、システムカタログスキーマ(pg_catalog)が含まれています。pg_catalogスキーマには、システムテーブルとすべての組み込みデータ型、関数、および演算子が含まれています。デフォルトではpg_catalogはスキーマ検索パスの先頭に暗黙的に含まれており、優先して検索されます。もし、pg_catalogスキーマの検索順を先頭以外に変更したい場合は、明示的にスキーマ検索パスにpg_catalogを追加します。 
- 
				スキーマ検索パスに設定したスキーマに、目的とするテーブルが存在するかは、以下例のようなスキーマ内のテーブル名一覧を出力(例:スキーマ名「user01」)する¥dtコマンドを実行します。 ¥dt user01.*コマンドが実行されると以下例のように表示され、存在が確認できます。 リレーション一覧 スキーマ | 名前 | タイプ | 所有者 ----------+-------+----------+-------- user01 | sales | テーブル | user01
参考
PostgreSQL 14文書
- 
				Documentation(PostgreSQLオフィシャル)
				- II. The SQL Language
						- 5.9 Schemas
								- 5.9.3 The Schema Search Path
 
 
- 5.9 Schemas
								
 
- II. The SQL Language
						
- 
				PostgreSQL日本語ドキュメント(日本PostgreSQLユーザ会)
				- II. SQL言語
						- 5.9. スキーマ
								- 5.9.3 スキーマ検索パス
 
 
- 5.9. スキーマ
								
 
- II. SQL言語
						
2023年4月12日更新
富士通のソフトウェア公式チャンネル(YouTube)
- 
					- 富士通のミドルウェア製品のご紹介や各種イベント・セミナーの講演内容、デモンストレーションなどの動画をご覧いただけます。
 
- 富士通のミドルウェア製品のご紹介や各種イベント・セミナーの講演内容、デモンストレーションなどの動画をご覧いただけます。
PostgreSQLについてより深く知る
PostgreSQLに興味をお持ちのお客様はこちらのコンテンツもお勧めです。ぜひご覧ください。
 
                                 
                                         
                                         
                                         
					 
					 
					