sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man kontrollerar om en tabell finns i ett givet schema

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 även pg_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



  1. Hitta 2:a högsta lönen bästa möjliga sätt

  2. Syntaxfel hos eller nära användare när Postgres-begränsning läggs till

  3. Får fel:Peer-autentisering misslyckades för användare postgres, när man försöker få pgsql att fungera med rails

  4. Hur hittar man n:e ranking i MySQL?