2013-10-25 8 views
0

Мой вопрос в два раза. Во-первых, я должен оценить версию PostgreSQL, чтобы запустить правильный запрос. У меня есть несколько серверов, на которых запущен PostgreSQL 8. * и у меня есть проблемы с использованием DO в моем запросе ниже. У серверов, на которых я запущен 9. * (в основном я использую сервер 9.2), выдает мне сообщение об ошибке: «запрос не имеет назначения для данных результата», когда все, что я хочу, является печатью из инструкции select.В запросе нет адресата для данных результата

Мой запрос:

DO 
$BODY$ 
BEGIN 
IF (SELECT setting from pg_settings where name = 'server_version') >= '9.2' THEN 
    SELECT pg_database.datname AS Database_Name, pg_authid.rolname AS Database_Owner, 
    pg_authid.rolsuper AS IsSuperUser, pg_tablespace.spcname AS TableSpaceName, 
    pg_catalog.pg_tablespace_location(pg_tablespace.oid) AS TableSpaceLocation 
    FROM pg_database 
    JOIN pg_authid on pg_database.datdba = pg_authid.oid 
    CROSS JOIN pg_tablespace 
    WHERE datistemplate = false 
    AND pg_database.dattablespace = pg_tablespace.oid; 
ELSE 
    SELECT pg_database.datname AS Database_Name, pg_authid.rolname AS Database_Owner, 
    pg_authid.rolsuper AS IsSuperUser, pg_tablespace.spcname AS TableSpaceName, pg_tablespace.spclocation AS TableSpaceLocation 
    FROM pg_database 
    JOIN pg_authid on pg_database.datdba = pg_authid.oid 
    CROSS JOIN pg_tablespace 
    WHERE datistemplate = false 
    AND pg_database.dattablespace = pg_tablespace.oid; 
END IF; 
END; 
$BODY$ 

Так что, если DO не работает предварительный 9.0, и я получаю ошибку после 9.0 я вроде застрял на том, что я могу сделать, чтобы удовлетворить обоим условиям.

+1

Используйте PERFORM вместо SELECT –

+1

Вы можете либо проверить версию сервера на клиенте перед отправкой запроса (таким образом, избегая конструкцию 'DO'), либо создать собственную функцию' pg_tablespace_location' на серверах 8.x таким образом что тот же запрос будет работать на всех версиях сервера. –

ответ

2

Оператор DO не может возвращать или выводить данные. manual page for DO описывает это следующим образом:

Кодовый блок обрабатывается так, как если бы он был телом функции без параметров, возвращающих пустоту.

Обратите внимание, что функция здесь не похожа на хранимую процедуру в других СУБД: вы не можете «выводить» набор результатов на полпути через функцию, но должны явно возвращать определенное значение. Для того, чтобы получить набор результатов, можно определить тип возвращаемого SETOF что-то, а затем можно запустить SELECT * FROM some_set_returning_function('some_param');

Кроме того, DO заявление было добавлено только в Postgres 9.0, так что тестирование для более ранних версий внутри такого утверждения, как и у вас есть нашел, не собирается работать.

Что вам нужно сделать, это либо сменить процедурные логики (IF) на вызывающее приложение, либо написать полную функцию pl/pgSQL для всего или части вашего запроса. Если вы вернете его, то можете использовать RETURN QUERY SELECT ... и поместить весь запрос в тело функции. Если вам нужно поддерживать Postgres 8.2 или ниже, вам нужно будет использовать петлю и RETURN NEXT.

Кстати, обратите внимание, что PostgreSQL сбрасывает имена столбцов в нижний регистр на выходе, если явно не указано, поэтому, например, TableSpaceLocation вернется в ваше приложение как tablespacelocation. Я настоятельно рекомендую вам использовать все строчные идентификаторы с разделителями нижнего регистра, чтобы избежать путаницы, например. table_space_location. Если вы должны сохранить регистр, используйте двойные кавычки, чтобы избежать точной строки, например. "TableSpaceLocation"; это затем обрабатывается как отдельный идентификатор из версии без кавычек или всего нижнего регистра.

Смежные вопросы