To zależy od tego, co chcesz dokładnie przetestować .
Schemat informacji?
Aby dowiedzieć się, „czy stół istnieje” (niezależnie od tego, kto pyta ), odpytywanie schematu informacji (information_schema.tables
) jest nieprawidłowe , ściśle mówiąc, ponieważ (według dokumentacji):
Wyświetlane są tylko te tabele i widoki, do których bieżący użytkownik ma dostęp (poprzez bycie właścicielem lub posiadanie uprawnień).
Zapytanie dostarczone przez @kong może zwrócić FALSE
, ale tabela może nadal istnieć. Odpowiada na pytanie:
Jak sprawdzić, czy istnieje tabela (lub widok) i czy bieżący użytkownik ma do niej dostęp?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Schemat informacji jest przydatny głównie do zachowania mobilności w głównych wersjach i różnych RDBMS. Jednak implementacja jest powolna, ponieważ Postgres musi używać zaawansowanych widoków, aby zachować zgodność ze standardem (information_schema.tables
jest dość prostym przykładem). Niektóre informacje (takie jak identyfikatory OID) giną w tłumaczeniu z katalogów systemowych - co właściwie nosić wszystkie informacje.
Katalogi systemowe
Twoje pytanie brzmiało:
Jak sprawdzić, czy tabela istnieje?
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
);
Użyj katalogów systemowych pg_class
i pg_namespace
bezpośrednio, co jest również znacznie szybsze. Jednak zgodnie z dokumentacją na pg_class
:
Katalog pg_class
kataloguje tabele i prawie wszystko, co ma kolumny lub jest w inny sposób podobne do tabeli. Obejmuje to indeksy (ale zobacz także pg_index
), sekwencje , wyświetlenia , widoki zmaterializowane , typy złożone i stoły TOSTY;
W przypadku tego konkretnego pytania możesz również użyć widoku systemowego pg_tables
. Nieco prostsze i bardziej przenośne w głównych wersjach Postgresa (co nie jest problemem w przypadku tego podstawowego zapytania):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Identyfikatory muszą być unikalne wśród wszystkich obiekty wymienione powyżej. Jeśli chcesz zapytać:
Jak sprawdzić, czy nazwa tabeli lub podobnego obiektu w danym schemacie jest zajęta?
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'
);
- Powiązana odpowiedź na dba.SE omawiająca „Schemat informacji a katalogi systemowe”
Alternatywnie:rzutuj na regclass
SELECT 'schema_name.table_name'::regclass
To zgłasza wyjątek jeśli (opcjonalnie zakwalifikowana do schematu) tabela (lub inny obiekt o tej nazwie) nie istnieje.
Jeśli nie kwalifikujesz nazwy tabeli według schematu, rzutuj na regclass
domyślnie search_path
i zwraca OID dla pierwszej znalezionej tabeli — lub wyjątek, jeśli tabela nie znajduje się w żadnym z wymienionych schematów. Zauważ, że schematy systemowe pg_catalog
i pg_temp
(schemat dla tymczasowych obiektów bieżącej sesji) są automatycznie częścią search_path
.
Możesz użyć tego i złapać możliwy wyjątek w funkcji. Przykład:
- Sprawdź, czy sekwencja istnieje w Postgresie (plpgsql)
Zapytanie takie jak powyżej pozwala uniknąć możliwych wyjątków i dlatego jest nieco szybsze.
to_regclass(rel_name)
w Postgresie 9.4+
Znacznie prostsze teraz:
SELECT to_regclass('schema_name.table_name');
Taka sama jak obsada, ale zwraca ...
... null zamiast zgłaszania błędu, jeśli nazwa nie zostanie znaleziona