14

我有一个返回表的 Postgres 函数:

CREATE OR REPLACE FUNCTION testFunction() RETURNS TABLE(a int, b int) AS
$BODY$
DECLARE a int DEFAULT 0;
DECLARE b int DEFAULT 0;
BEGIN
CREATE TABLE tempTable AS SELECT a, b;
RETURN QUERY SELECT * FROM tempTable; 
DROP TABLE tempTable;
END;
$BODY$
LANGUAGE plpgsql;

此函数不以行和列的形式返回数据。相反,它将数据返回为:

(0,0)

这导致 Coldfusion cfquery 块在提取数据时出现问题。从该函数返回表时,如何获取行和列中的数据?换句话说:为什么 PL/pgSQL 函数不将数据作为列返回?

4

2 回答 2

31

要获取单个列而不是行类型,请使用以下命令调用该函数:

SELECT * FROM testfunction();

就像您从表中选择所有列一样。
还要考虑您的测试功能的这种审查形式:

CREATE OR REPLACE FUNCTION testfunction()
  RETURNS TABLE(a int, b int)
  LANGUAGE plpgsql AS
$func$
DECLARE
   _a int := 0;
   _b int := 0;
BEGIN
   CREATE TABLE tempTable AS SELECT _a, _b;
   RETURN QUERY SELECT * FROM tempTable;
   DROP TABLE tempTable;
END
$func$;

尤其:

DECLARE关键字只需要一次。

避免在子句中声明已经(隐式)声明为OUT参数的参数。RETURNS TABLE (...)

不要在 Postgres 中使用不带引号的 CaMeL-case 标识符。它可以工作,未加引号的标识符被转换为小写,但它可能导致令人困惑的错误。看:

示例中的临时表完全没用(可能过于简化)。给出的示例归结为:

CREATE OR REPLACE FUNCTION testfunction(OUT a int, OUT b int)
  LANGUAGE plpgsql AS
$func$
BEGIN
   a := 0;
   b := 0;
END
$func$;
于 2013-02-01T23:24:40.920 回答
4

当然,您可以通过将函数调用放在FROM子句中来做到这一点,就像 Eric Brandstetter 正确回答一样。但是,这有时会使 FROM 子句中已经包含其他内容的查询变得复杂。要获取函数返回的各个列,可以使用以下语法:

SELECT (testfunction()).*

或者只获取名为“a”的列:

SELECT (testfunction()).a

将整个函数(包括输入值)放在括号中,后跟一个点和所需的列名或星号。

要获取函数返回的列名,您必须:

  • 检查源代码
  • 首先检查函数的结果,如下所示:SELECT * FROM testfunction()

输入值仍然可以来自FROM子句。只是为了说明这一点,考虑这个函数和测试数据:

CREATE FUNCTION funky(a integer, b integer)
RETURNS TABLE(x double precision, y double precision) AS $$
 SELECT a*random(), b*random();
$$ LANGUAGE SQL;

CREATE TABLE mytable(a integer, b integer);
INSERT INTO mytable
    SELECT generate_series(1,100), generate_series(101,200);

您可以调用函数“funky(a,b)”,而无需将其放在FROM子句中:

SELECT (funky(mytable.a, mytable.b)).*
FROM mytable;

这将导致2列:

         x         |         y         
-------------------+-------------------
 0.202419687062502 |   55.417385618668
  1.97231830470264 |  63.3628275180236
  1.89781916560605 |  1.98870931006968
(...)
于 2020-01-10T15:11:22.237 回答