Postgres 8.4以降のデータベースにはpublic
スキーマに共通のテーブルがあり、company
スキーマに会社固有のテーブルがあります。company
スキーマ名は常に'company'
で始まり、会社番号で終わります。
したがって、次のようなスキーマがあるかもしれません。
public
company1
company2
company3
...
companynn
アプリケーションは常に単一の会社で機能します。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以降で動作するはずです。
テストする対象によって異なりますexactly。
「テーブルが存在するかどうか」(誰が尋ねても)を見つけるには、情報スキーマ(information_schema.tables
)のクエリはincorrect、厳密に言えば、( per documentation ):
現在のユーザーがアクセスできるテーブルとビューのみが表示されます(所有者である、または何らかの特権を持つ)。
クエリ @kongで示される はFALSE
を返すことができますが、テーブルはまだ存在できます。それは質問に答えます:
テーブル(またはビュー)が存在し、現在のユーザーがそれにアクセスできるかどうかを確認する方法は?
SELECT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
情報スキーマは、主に、メジャーバージョン間および異なるRDBMS間で移植性を維持するのに役立ちます。しかし、Postgresは洗練されたビューを使用して標準に準拠する必要があるため、実装は遅くなります(information_schema.tables
はかなり単純な例です)。また、一部の情報(OIDなど)は、システムカタログからの翻訳で失われます-実際にはすべての情報を保持しています。
あなたの質問は:
テーブルが存在するかどうかを確認する方法は?
SELECT EXISTS (
SELECT 1
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_class
およびpg_namespace
を直接使用します。これもかなり高速です。ただし、 pg_class
のドキュメントごと :
カタログ
pg_class
は、テーブルと、列を持っているかテーブルに類似している他のほとんどすべてをカタログします。これには、indexes(ただしpg_index
も参照)、sequences、views、マテリアライズドビュー、コンポジットタイプ、およびTOASTテーブル;
この特定の質問には、 システムビューpg_tables
も使用できます。主要なPostgresバージョン間で少しシンプルで移植性が高い(この基本的なクエリにはほとんど関心がありません):
SELECT EXISTS (
SELECT 1
FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
識別子は、上記のallオブジェクト間で一意である必要があります。質問したい場合:
特定のスキーマ内のテーブルまたは同様のオブジェクトの名前が使用されているかどうかを確認する方法
SELECT EXISTS (
SELECT 1
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');
キャストと同じ、 but返される...
...名前が見つからない場合はエラーをスローするのではなくnull
おそらく information_schema :を使ってください。
SELECT EXISTS(
SELECT *
FROM information_schema.tables
WHERE
table_schema = 'company3' AND
table_name = 'tableincompany3schema'
);
私の古いSwissKnifeライブラリには、relname_exists(anyThing)
、relname_normalized(anyThing)
、relnamechecked_to_array(anyThing)
の3種類があります。すべて--- pg_catalog.pg_classテーブルからチェックし、標準のユニバーサルデータ型を返します(boolean、textまたはtext [])。 。
/**
* From my old SwissKnife Lib to your SwissKnife. License CC0.
* Check and normalize to array the free-parameter relation-name.
* Options: (name); (name,schema), ("schema.name"). Ignores schema2 in ("schema.name",schema2).
*/
CREATE FUNCTION relname_to_array(text,text default NULL) RETURNS text[] AS $f$
SELECT array[n.nspname::text, c.relname::text]
FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace,
regexp_split_to_array($1,'\.') t(x) -- not work with quoted names
WHERE CASE
WHEN COALESCE(x[2],'')>'' THEN n.nspname = x[1] AND c.relname = x[2]
WHEN $2 IS NULL THEN n.nspname = 'public' AND c.relname = $1
ELSE n.nspname = $2 AND c.relname = $1
END
$f$ language SQL IMMUTABLE;
CREATE FUNCTION relname_exists(text,text default NULL) RETURNS boolean AS $wrap$
SELECT EXISTS (SELECT relname_to_array($1,$2))
$wrap$ language SQL IMMUTABLE;
CREATE FUNCTION relname_normalized(text,text default NULL,boolean DEFAULT true) RETURNS text AS $wrap$
SELECT COALESCE(array_to_string(relname_to_array($1,$2), '.'), CASE WHEN $3 THEN '' ELSE NULL END)
$wrap$ language SQL IMMUTABLE;