0

我的问题是两方面的。首先,我必须评估 PostgreSQL 的版本才能运行正确的查询。DO我有一些运行 PostgreSQL 8.* 的服务器,它们在下面的查询中使用时遇到问题。我运行 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 之后收到错误,我有点坚持我能做些什么来满足这两个条件。

4

1 回答 1

3

DO语句不能返回或输出任何数据。手册页是DO这样描述的:

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

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

此外,该DO语句仅在 Postgres 9.0 中添加,因此如您所见,在这样的语句中测试早期版本是行不通的。

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

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

于 2013-10-25T16:03:10.873 回答