SQL запрос к таблице, которая может отсутствовать PostgreSQL
Возникла проблема при попытке написать SQL-запрос к таблице, которая может отсутствовать, тк целевой скрипт будет прогоняться на разных БД. Ранее осуществлял проверку наличия таблице путем использования exists:
SELECT EXISTS(SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'public' and table_name = 'TRO-LO-LO')
Если есть хотя бы одна строка - 't', нет - 'f'. Всегда работало как по маслу. Конечно, не самый изощренный и оправданный способ, но работает же(работал), пока не столкнулся с проблемой применения данной проверки в запросе на выборку кортежей по нескольким атрибутам. Если я использую данную проверку и добавляю к нему условный оператор CASE:
SELECT CASE WHEN EXISTS(SELECT * FROM information_schema.tables
WHERE table_schema = 'public' and table_name = 'TRO-LO-LO') = 't' THEN (SELECT id, STA
FROM TRO-LO-LO)
ELSE 0
END;
Учитывая то, что подзапрос может вернуть только данные по одному атрибуту, получаем ошибку
subquery must return only one column
Внимание! Вопрос! Как реализовать в одном sql запросе проверку наличия целевой таблицы и выборку по нескольким колонкам? Конечно, если таблица имеется - вывести выборку, если таблицы нет - вернуть 0/null.
Цель: 0. Осуществить проверку наличия таблицы.
- Если таблица имеется - получить данные по нескольким атрибутам(плюс агрегатный count), если нет вернуть нуль.
- Получить прилив эндорфина в следствии получения ответа от более смышленых пользователей StOw.
Спасибо.
Ответы (1 шт):
В контексте оператора EXISTS любой вывод не имеет смысла, так как он выполняется до первой записи, это одна из причин его эффективности при наличии совпадений. PostgreSQL богат своей справочной системой, подробно описывающей в том числе системные каталоги, если задачи обеспечения переносимости SQL не стоит, то вашу задачу можно реализовать с использованием данных системных каталогов: pg_attribute, pg_class. Вы можете за один шаг проверить как наличие таблицы, так и проверить наличие атрибутов (полей). Покажу на примере системного каталога pg_class, я формирую только проверку условия так как судя по всему вы знаете что с ним делать:
SELECT COALESCE((SELECT EXISTS(SELECT FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
WHERE (c.relname = 'pg_class') AND (a.attname = 'relname'))), false);
SELECT COALESCE((WITH ta(attname) AS
( SELECT array_agg(a.attname) FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
WHERE (c.relname = 'pg_class') AND (a.attnum >0)
)
SELECT (SELECT attname FROM ta LIMIT 1)::text[] @> ARRAY['relname', 'reloftype']), false);
Рабочий пример, с которым можно экспериментировать здесь