查询没有结果数据的目的地

时间:2013-10-25 15:07:54

标签: sql postgresql plpgsql

我的问题有两个问题。首先,我必须评估PostgreSQL的版本才能运行正确的查询。我有一些运行PostgreSQL 8. *的服务器,他们在下面的查询中使用DO时遇到问题。我运行的服务器9. *(主要是我使用的是9.2服务器)给我一个错误“查询没有结果数据的目的地”,当我想要的是打印出选择语句时。

我的查询:

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 个答案:

答案 0 :(得分:2)

DO语句无法返回或输出任何数据。 manual page for DO因此描述了它:

  

代码块被视为没有参数的函数体,返回void。

请注意,此处的函数与其他DBMS中的存储过程不同:您不能在函数中途“输出”结果集,但必须显式返回某个特定值。要获取结果集,请将返回类型定义为SETOF,然后运行SELECT * FROM some_set_returning_function('some_param');

此外,DO语句仅在Postgres 9.0中添加,因此在此类语句中对早期版本的测试正如您所发现的那样无法正常工作。

您需要做的是将程序逻辑(IF)转移到调用应用程序中,或者为您的全部或部分查询编写完整的pl/pgSQL函数。如果您返回SETOF RECORD,则可以使用RETURN QUERY SELECT ...并将整个查询放在函数体内。如果您需要支持Postgres 8.2或更低版本,则需要使用循环并RETURN NEXT代替。

顺便提一下,请注意PostgreSQL在输出时将列名称折叠为小写,除非明确引用,因此例如TableSpaceLocation将以tablespacelocation的形式返回到您的应用程序。我强烈建议您始终使用全小写下划线分隔标识符以避免混淆,例如table_space_location。如果必须保留大小写,请使用双引号来转义确切的字符串,例如"TableSpaceLocation";然后将其视为不带引号或全小写版本的不同标识符。