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. Осуществить проверку наличия таблицы.

  1. Если таблица имеется - получить данные по нескольким атрибутам(плюс агрегатный count), если нет вернуть нуль.
  2. Получить прилив эндорфина в следствии получения ответа от более смышленых пользователей StOw.

Спасибо.


Ответы (1 шт):

Автор решения: Dmitry Ivanov

В контексте оператора 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);

Рабочий пример, с которым можно экспериментировать здесь

→ Ссылка