【问题标题】:Query has no destination for result data查询没有结果数据的目的地
【发布时间】:2013-10-25 15:07:53
【问题描述】:

我的问题有两个。首先,我必须评估 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 之后遇到错误,那么我有点难以满足这两个条件。

【问题讨论】:

  • 使用 PERFORM 代替 SELECT
  • 您可以在提交查询之前在客户端测试服务器版本(从而避免 DO 构造),或者在 8.x 服务器上创建自己的 pg_tablespace_location 函数,其方式如下:相同的查询将适用于所有服务器版本。

标签: sql postgresql plpgsql


【解决方案1】:

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";然后将其视为与未加引号或全小写版本不同的标识符。

【讨论】:

    猜你喜欢
    • 2016-02-23
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多