195

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 以降で動作するはずです。

4

4 に答える 4

353

何を正確にテストしたいかによって異なります。

情報スキーマ?

「テーブルが存在するかどうか」(誰が尋ねても) を見つけるために、情報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_catalogおよびpg_temp(現在のセッションの一時オブジェクトのスキーマ) は、自動的にsearch_path.

それを使用して、関数で発生する可能性のある例外をキャッチできます。例:

上記のようなクエリは、発生する可能性のある例外を回避するため、わずかに高速です。

to_regclass(rel_name)Postgres 9.4 以降で

はるかに簡単になりました:

SELECT to_regclass('schema_name.table_name');

キャストと同じです、戻ってきます...

...名前が見つからない場合にエラーをスローするのではなく、null

于 2014-06-06T19:58:11.623 に答える