Det afhænger af, hvad du vil teste præcis .
Oplysningsskema?
For at finde "om bordet eksisterer" (uanset hvem der spørger ), forespørger informationsskemaet (information_schema.tables
) er forkert , strengt taget, fordi (pr. dokumentation):
Kun de tabeller og visninger vises, som den aktuelle bruger har adgang til (ved at være ejer eller have et privilegium).
Forespørgslen leveret af @kong kan returnere FALSE
, men tabellen kan stadig eksistere. Det besvarer spørgsmålet:
Hvordan kontrollerer man, om en tabel (eller visning) eksisterer, og den aktuelle bruger har adgang til den?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Informationsskemaet er hovedsageligt nyttigt til at forblive bærbart på tværs af større versioner og på tværs af forskellige RDBMS. Men implementeringen er langsom, fordi Postgres skal bruge sofistikerede visninger for at overholde standarden (information_schema.tables
er et ret simpelt eksempel). Og nogle oplysninger (som OID'er) går tabt i oversættelsen fra systemkatalogerne - hvilket faktisk bære alle oplysninger.
Systemkataloger
Dit spørgsmål var:
Hvordan kontrollerer man, om en tabel eksisterer?
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
);
Brug systemkatalogerne pg_class
og pg_namespace
direkte, hvilket også er betydeligt hurtigere. Dog pr. dokumentation på pg_class
:
Kataloget pg_class
katalogiserer tabeller og det meste andet, der har kolonner eller på anden måde ligner en tabel. Dette inkluderer indekser (men se også pg_index
), sekvenser , visninger , materialiserede visninger , sammensatte typer , og TOAST-tabeller;
Til dette specifikke spørgsmål kan du også bruge systemvisningen pg_tables
. Lidt enklere og mere bærbar på tværs af større Postgres-versioner (hvilket næppe er bekymrende for denne grundlæggende forespørgsel):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Identifikatorer skal være unikke blandt alle genstande nævnt ovenfor. Hvis du vil spørge:
Hvordan kontrollerer man, om et navn til en tabel eller lignende objekt i et givet skema er taget?
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'
);
- Relateret svar på dba.SE om "Informationsskema vs. systemkataloger"
Alternativ:cast til regclass
SELECT 'schema_name.table_name'::regclass
Dette hæver en undtagelse hvis den (valgfrit skema-kvalificerede) tabel (eller et andet objekt, der optager det navn) ikke eksisterer.
Hvis du ikke skemakvalificerer tabelnavnet, en cast til regclass
er standard til search_path
og returnerer OID for den første fundne tabel - eller en undtagelse, hvis tabellen ikke er i nogen af de anførte skemaer. Bemærk, at systemskemaerne pg_catalog
og pg_temp
(skemaet for midlertidige objekter i den aktuelle session) er automatisk en del af search_path
.
Du kan bruge det og fange en mulig undtagelse i en funktion. Eksempel:
- Tjek, om sekvensen findes i Postgres (plpgsql)
En forespørgsel som ovenfor undgår mulige undtagelser og er derfor lidt hurtigere.
to_regclass(rel_name)
i Postgres 9.4+
Meget enklere nu:
SELECT to_regclass('schema_name.table_name');
Samme som rollebesætningen, men det returnerer ...
... null i stedet for at smide en fejl, hvis navnet ikke findes