Це залежить від того, що ви хочете точно протестувати .
Інформаційна схема?
Щоб знайти "чи існує таблиця" ( незалежно від того, хто запитує ), запит на інформаційну схему ( information_schema.tables
) неправильний , строго кажучи, тому що ( за документацією ):
Показано лише ті таблиці та представлення, до яких поточний користувач має доступ (як власник або певний привілей).
Запит, наданий @kong, може повернутися FALSE
, але таблиця все ще може існувати. Він відповідає на питання:
Як перевірити, чи існує таблиця (або представлення) і чи має поточний користувач доступ до неї?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Інформаційна схема в основному корисна для того, щоб залишатися переносними для основних версій та для різних RDBMS. Але реалізація відбувається повільно, оскільки Postgres повинен використовувати складні представлення, щоб відповідати стандарту ( information_schema.tables
досить простий приклад). І деяка інформація (як OID) втрачається при перекладі з системних каталогів - що насправді несуть усю інформацію.
Системні каталоги
Ваше питання:
Як перевірити, чи існує таблиця?
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
);
Використовуйте системні каталоги pg_class
та pg_namespace
безпосередньо, що також значно швидше. Однак відповідно до документації щодоpg_class
:
Каталог pg_class
каталогізує таблиці та більшість всього іншого, що має стовпці або схожим на таблицю. Сюди входять індекси (але див. Також pg_index
), послідовності , види , матеріалізовані подання , складені типи та таблиці TOAST ;
Для цього конкретного питання ви також можете скористатися поданням системиpg_tables
. Трохи простіша та портативніша версія для основних версій Postgres (що навряд чи стосується цього базового запиту):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Ідентифікатори повинні бути унікальними серед усіх згаданих вище об'єктів. Якщо ви хочете запитати:
Як перевірити, чи береться ім’я таблиці або подібного об’єкта в заданій схемі?
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'
);
Альтернатива: кинути в regclass
SELECT 'schema_name.table_name'::regclass
Це створює виняток, якщо таблиця (за бажанням схеми) (або інший об'єкт, що займає це ім'я) не існує.
Якщо ви не класифікуєте схему назви таблиці, призначається regclass
значення за замовчуванням до search_path
та повертає OID для першої знайденої таблиці - або виняток, якщо таблиця не міститься в жодній із перелічених схем. Зауважте, що системні схеми pg_catalog
та pg_temp
(схема тимчасових об'єктів поточного сеансу) автоматично є частиною search_path
.
Ви можете використовувати це і вловлювати можливий виняток у функції. Приклад:
Запит, як описано вище, дозволяє уникнути можливих винятків і тому трохи швидший.
Набагато простіше зараз:
SELECT to_regclass('schema_name.table_name');
Те саме, що в ролях, але повертається ...
... нуль, а не видача помилки, якщо ім'я не знайдено
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]