Es hängt davon ab, was Sie genau testen möchten .
Informationsschema?
Um herauszufinden, ob die Tabelle existiert ( egal wer fragt ), ist das Abfragen des Informationsschemas ( information_schema.tables
) streng genommen falsch , weil ( gemäß Dokumentation ):
Es werden nur die Tabellen und Ansichten angezeigt, auf die der aktuelle Benutzer Zugriff hat (als Eigentümer oder mit Berechtigungen).
Die von @kong bereitgestellte Abfrage kann zurückgegeben werden FALSE
, die Tabelle kann jedoch weiterhin vorhanden sein. Es beantwortet die Frage:
Wie überprüfe ich, ob eine Tabelle (oder Ansicht) vorhanden ist und der aktuelle Benutzer Zugriff darauf hat?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Das Informationsschema ist hauptsächlich nützlich, um über Hauptversionen und über verschiedene RDBMS hinweg portabel zu bleiben. Die Implementierung ist jedoch langsam, da Postgres ausgefeilte Ansichten verwenden muss, um dem Standard zu entsprechen (dies information_schema.tables
ist ein recht einfaches Beispiel). Und einige Informationen (wie OIDs) gehen bei der Übersetzung aus den Systemkatalogen verloren - die tatsächlich alle Informationen enthalten.
Systemkataloge
Ihre Frage war:
Wie überprüfe ich, ob eine Tabelle existiert?
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
);
Verwenden Sie die Systemkataloge pg_class
und pg_namespace
direkt, was auch erheblich schneller ist. Jedoch pro Dokumentation aufpg_class
:
Der Katalog pg_class
katalogisiert Tabellen und fast alles andere, was Spalten enthält oder auf andere Weise einer Tabelle ähnelt. Dies umfasst Indizes (siehe auch pg_index
), Sequenzen , Ansichten , materialisierte Ansichten , zusammengesetzte Typen und TOAST-Tabellen .
Für diese spezielle Frage können Sie auch die Systemansicht verwendenpg_tables
. Ein bisschen einfacher und portabler für alle wichtigen Postgres-Versionen (was für diese grundlegende Abfrage kaum von Belang ist):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Bezeichner müssen unter allen oben genannten Objekten eindeutig sein . Wenn Sie fragen möchten:
Wie kann überprüft werden, ob ein Name für eine Tabelle oder ein ähnliches Objekt in einem bestimmten Schema verwendet wird?
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'
);
Alternative: Besetzung zu regclass
SELECT 'schema_name.table_name'::regclass
Dies löst eine Ausnahme aus, wenn die (optional schemaqualifizierte) Tabelle (oder ein anderes Objekt, das diesen Namen belegt) nicht vorhanden ist.
Wenn Sie den Tabellennamen nicht schemaqualifizieren, wird regclass
standardmäßig eine Umwandlung in die zurückgegeben search_path
und die OID für die erste gefundene Tabelle zurückgegeben - oder eine Ausnahme, wenn sich die Tabelle in keinem der aufgelisteten Schemas befindet. Beachten Sie, dass die Systemschemata pg_catalog
und pg_temp
(das Schema für temporäre Objekte der aktuellen Sitzung) automatisch Teil von sind search_path
.
Sie können das verwenden und eine mögliche Ausnahme in einer Funktion abfangen. Beispiel:
Eine Abfrage wie oben vermeidet mögliche Ausnahmen und ist daher etwas schneller.
Viel einfacher jetzt:
SELECT to_regclass('schema_name.table_name');
Wie die Besetzung, aber es kehrt zurück ...
... null anstatt einen Fehler auszulösen, wenn der Name nicht gefunden wird
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]
pg_tables
ist eigentlich eine gute Idee für "Wie überprüfe ich, ob eine Tabelle existiert?" (Für die Überprüfung von Tabellen nur ., Nicht für andere Zwecke, wie oben erklärt sich auch,pg_tables
eine Ansicht mit mehreren Tabellen (pg_class
,pg_namespace
,pg_tablespace
), das ist ein bisschen teurer Der wichtigste Grund:. Ich Abfrage verwendet binpg_class
direkt und tat es nicht Denken Sie daran,pg_tables
wenn Sie diese Antwort schreiben. Ich habe sie jetzt oben hinzugefügt, danke.pg_my_temp_schema()
, um die OID des tatsächlichen temporären Schemas abzurufen, falls vorhanden. (Aber Ansichten in derinformation_schema
enthalten keine OIDs. Sie könntenSELECT nspname FROM pg_namespace WHERE OID = pg_my_temp_schema()
) Ihr Test hat mehrere Schwächen. Ein korrekter Test wäretable_schema LIKE 'pg\_temp\_%'
oder strenger :table_schema ~ '^pg_temp_\d+$'
.Verwenden Sie möglicherweise information_schema :
quelle
Für PostgreSQL 9.3 oder weniger ... Oder wer mag alle auf Text normalisiert
Drei Aromen meiner alten Bibliothek Swissknife:
relname_exists(anyThing)
,relname_normalized(anyThing)
undrelnamechecked_to_array(anyThing)
. Alle Überprüfungen aus der Tabelle pg_catalog.pg_class und geben universelle Standarddatentypen ( Boolescher Wert , Text oder Text []) zurück.quelle