Det beror på vad du vill testa exakt .
Informationsschema?
För att ta reda på "om tabellen finns" (oavsett vem som frågar ), frågar informationsschemat (information_schema.tables
) är felaktig , strängt taget, eftersom (per dokumentation):
Endast de tabeller och vyer visas som den aktuella användaren har tillgång till (genom att vara ägare eller ha något privilegium).
Frågan från @kong kan returnera FALSE
, men tabellen kan fortfarande existera. Det svarar på frågan:
Hur kontrollerar man om en tabell (eller vy) finns och den aktuella användaren har tillgång till den?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Informationsschemat är främst användbart för att förbli portabelt över större versioner och över olika RDBMS. Men implementeringen är långsam, eftersom Postgres måste använda sofistikerade vyer för att följa standarden (information_schema.tables
är ett ganska enkelt exempel). Och viss information (som OID) går förlorad vid översättning från systemkatalogerna - vilket faktiskt bär all information.
Systemkataloger
Din fråga var:
Hur kontrollerar man om en tabell finns?
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
);
Använd systemkatalogerna pg_class
och pg_namespace
direkt, vilket också är betydligt snabbare. Men enligt dokumentation på pg_class
:
Katalogen
pg_class
katalogiserar tabeller och nästan allt annat som har kolumner eller på annat sätt liknar en tabell. Detta inkluderar index (men se ävenpg_index
), sekvenser , visningar , materialiserade vyer , komposittyper och TOAST-tabeller;
För just denna fråga kan du också använda systemvyn pg_tables
. Lite enklare och mer bärbar över större Postgres-versioner (vilket knappast är något som är oroande för denna grundläggande fråga):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Identifierare måste vara unika bland alla objekt som nämns ovan. Om du vill fråga:
Hur kontrollerar man om ett namn för en tabell eller liknande objekt i ett givet schema tas?
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'
);
- Relaterat svar på dba.SE som diskuterar "Informationsschema kontra systemkataloger"
Alternativ:casta till regclass
SELECT 'schema_name.table_name'::regclass
Detta uppstår ett undantag om den (valfritt schemakvalificerade) tabellen (eller annat objekt som upptar det namnet) inte finns.
Om du inte schemakvalificerar tabellnamnet, en cast till regclass
är standard till search_path
och returnerar OID för den första tabellen som hittas - eller ett undantag om tabellen inte finns i något av de listade schemana. Observera att systemschemana pg_catalog
och pg_temp
(schemat för temporära objekt för den aktuella sessionen) är automatiskt en del av search_path
.
Du kan använda det och fånga ett möjligt undantag i en funktion. Exempel:
- Kontrollera om sekvensen finns i Postgres (plpgsql)
En fråga som ovan undviker möjliga undantag och är därför något snabbare.
to_regclass(rel_name)
i Postgres 9.4+
Mycket enklare nu:
SELECT to_regclass('schema_name.table_name');
Samma som skådespelaren, men den returnerar ...
... null istället för att skicka ett felmeddelande om namnet inte hittas