1. ホーム
  2. sql

[解決済み] 指定されたスキーマにテーブルが存在するかどうかを確認する方法

2022-03-13 14:55:01

質問

Postgres 8.4 以降のデータベースでは、共通テーブルを public スキーマに、会社独自のテーブルを company スキーマを使用します。
company スキーマ名は常に 'company' で終わり、会社番号で終わります。
というようなスキーマがあるかもしれませんね。

public
company1
company2
company3
...
companynn

アプリケーションは常に1社で動作します。
search_path は、odbcやnpgsqlの接続文字列で適宜指定してください。

search_path='company3,public'

指定されたテーブルが、指定されたディレクトリに存在するかどうかをどのように確認しますか? companyn スキーマは?

などです。

select isSpecific('company3','tablenotincompany3schema')

を返さなければなりません。 false そして

select isSpecific('company3','tableincompany3schema')

を返さなければなりません。 true .

いずれにせよ、この関数がチェックすべきなのは companyn スキーマが渡され、他のスキーマは渡されない。

あるテーブルが public と渡されたスキーマを比較した場合、この関数は true .
Postgres 8.4 以降で動作するはずです。

解決方法は?

何をテストしたいかによります まさに .

情報スキーマ?

テーブルが存在するかどうかを調べるには、( 誰が聞いても )、情報スキーマを問い合わせる( information_schema.tables ) は 不正解 は、厳密には、( ドキュメントに基づく ):

現在のユーザーがアクセスできるテーブルとビューのみが表示されます。 に(所有者であるか、何らかの特権を持っていることによって)アクセスすることができます。

クエリ 提供:@kong を返すことができます。 FALSE しかし、そのテーブルはまだ存在することができます。質問に答えています。

テーブル(またはビュー)が存在し、現在のユーザーがそれにアクセスできるかどうかを確認するにはどうすればよいですか?

SELECT EXISTS (
   SELECT FROM information_schema.tables 
   WHERE  table_schema = 'schema_name'
   AND    table_name   = 'table_name'
   );

情報スキーマは、主にメジャーバージョンや異なるRDBMS間で移植性を維持するために有用です。しかし、Postgresは標準に準拠するために洗練されたビューを使用しなければならないため、実装には時間がかかります ( information_schema.tables は、かなり単純な例です)。そして、いくつかの情報(OIDなど)はシステムカタログからの翻訳で失われます。 実は はすべての情報を持っています。

システムカタログ

ご質問の内容は

テーブルが存在するかどうかを確認する方法は?

SELECT EXISTS (
   SELECT FROM pg_catalog.pg_class c
   JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
   WHERE  n.nspname = 'schema_name'
   AND    c.relname = 'table_name'
   AND    c.relkind = 'r'    -- only tables
   );

システムカタログを利用する pg_classpg_namespace を直接実行することで、これもかなり高速になります。しかし のドキュメントによると pg_class :

カタログ pg_class は、テーブルと、それ以外のほとんどすべての カラムを持つか、あるいはテーブルに類似している。これには インデックス (ただし も参照してください。 pg_index ), シーケンス , ビュー , マテリアライズド・ビュー , コンポジット タイプ そして TOAST テーブル ;

この特定の質問に対しては システムビュー pg_tables . もう少しシンプルで、主要なPostgresのバージョン間でよりポータブルです(この基本的なクエリではほとんど気にする必要はありません)。

SELECT EXISTS (
   SELECT FROM pg_tables
   WHERE  schemaname = 'schema_name'
   AND    tablename  = 'table_name'
   );

の間で一意である必要があります。 すべて オブジェクトがあります。もし聞きたいのなら

与えられたスキーマのテーブルなどの名前が取られているかどうかを確認する方法は?

SELECT EXISTS (
   SELECT FROM pg_catalog.pg_class c
   JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
   WHERE  n.nspname = 'schema_name'
   AND    c.relname = 'table_name'
   );

代替:キャスト regclass

SELECT 'schema_name.table_name'::regclass

これは は例外を発生させます。 (オプションでスキーマ修飾された) テーブル (あるいはその名前を占める他のオブジェクト) が存在しない場合。

テーブル名をスキーマ修飾していない場合、テーブル名へのキャストを regclass はデフォルトで search_path を実行し、最初に見つかったテーブルのOIDを返します。テーブルがリストされたスキーマのいずれにも含まれていない場合は例外が発生します。なお、システムスキーマ pg_catalogpg_temp (現在のセッションの一時的なオブジェクトのスキーマ) は、自動的に search_path .

それを使って、関数の中で起こりうる例外をキャッチすることができます。例

上記のようなクエリは、起こりうる例外を回避することができるため、若干高速になります。

to_regclass(rel_name) Postgres 9.4+の場合

よりシンプルになりました。

SELECT to_regclass('schema_name.table_name');

キャストと同じです。 しかし を返します。

... 名前が見つからない場合にエラーを投げるのではなく、NULLを投げる