从PostgreSQL函数返回自定义类型

8
我将尝试从PostgreSQL函数中返回自定义类型,具体如下:
DROP TYPE IF EXISTS GaugeSummary_GetDateRangeForGauge_Type CASCADE; -- Drop our previous type

CREATE TYPE GaugeSummary_GetDateRangeForGauge_Type AS   -- Recreate our type    
(
    Minimum timestamp without time zone,
    Maximum timestamp without time zone
);


CREATE OR REPLACE FUNCTION GaugeSummary_GetDateRangeForGauge
(
    GaugeID integer
)
RETURNS GaugeSummary_GetDateRangeForGauge_Type AS 
$$
DECLARE
    iGaugeID ALIAS FOR $1;
    oResult     GaugeSummary_GetDateRangeForGauge_Type%ROWTYPE;
BEGIN
    SELECT INTO oResult
        min(ArchivedMinimumTime) as Minimum, 
        max(TelemeteredMaximumTime) as Maximum 
    FROM GaugeSummary 
    WHERE GaugeID = $1;

    RETURN oResult;
END;
$$ LANGUAGE plpgsql;

SELECT GaugeSummary_GetDateRangeForGauge(2291308);

我遇到了两个问题。

1) - 我的结果以 "("1753-01-01 12:00:00","2009-11-11 03:45:00")"的形式返回为单列,而我需要它们以两列的形式返回。

解决!- 愚蠢的错误... 应该是SELECT * FROM GaugeSummary_GetDateRangeForGauge(123)

2) 结果是整个表中的最大值和最小值 - WHERE约束没有被使用。

例如:

GaugeSummaryID  GaugeID   ArchivedMinimumTime   TelemeteredMaximumTime
80               4491   "2009-03-28 12:00:00"   "2009-06-27 12:00:00"
81               4491   "2009-03-28 12:00:00"   "2009-06-27 12:00:00"

但是调用该函数会给我:

"1753-01-01 12:00:00", "2009-11-11 03:45:00"

谢谢!

答案2:

似乎在“LANGUAGE 'SQL' STABLE;”函数内运行相同的查询可以正常工作:

CREATE OR REPLACE FUNCTION GaugeSummary_GetDateRangeForGauge
(
    GaugeID integer
)
RETURNS GaugeSummary_GetDateRangeForGauge_Type AS
$$
    SELECT min(ArchivedMinimumTime) as Minimum, 
        max(TelemeteredMaximumTime) as Maximum 
    FROM GaugeSummary WHERE GaugeID = $1;
$$ LANGUAGE 'SQL' STABLE;

然而,知道为什么plpgsql函数不能正确工作会很好...
1个回答

10

我尝试了这个,当执行时我得到了两列返回结果

SELECT * GaugeSummary_GetDateRangeForGauge(1);  

结果:

aadb=# select * from GaugeSummary_GetDateRangeForGauge(1);
      minimum               |          maximum
----------------------------+----------------------------
 2010-01-11 15:14:20.649786 | 2010-01-11 15:14:24.745783
(1 row)

我正在使用8.4版本并在psql中运行它。你能否澄清一下你是如何得到你的结果的?

至于第二个问题,如果你只想要结果,则从查询中删除min()和max()聚合函数。这样做将确保来自这些列的结果将返回匹配您ID的行。

更新: 好吧,我不确定发生了什么。我刚把所有类似的东西放到我的测试数据库中,它按照我期望的方式工作。

自定义类型

create type custom_type as ( 
   minimum timestamp without time zone, 
   maximum timestamp without time zone);

表格(测试)

aadb=# select * from test order by id;
 id |             a              |             b
----+----------------------------+----------------------------
  1 | 2010-01-11 17:09:52.329779 | 2010-01-11 17:09:52.329779
  1 | 2010-01-11 17:10:04.729776 | 2010-01-11 17:10:04.729776
  2 | 2010-01-11 17:09:55.049781 | 2010-01-11 17:10:21.753781
  2 | 2010-01-11 17:10:30.501781 | 2010-01-11 17:10:30.501781
  3 | 2010-01-11 17:09:58.289772 | 2010-01-11 17:09:58.289772
  3 | 2010-01-11 17:35:38.089853 | 2010-01-11 17:35:38.089853
(6 rows)

函数

create or replace function maxmin (pid integer) returns custom_type as $$ 
declare  
  oResult custom_type%rowtype; 
begin 
  select into oResult min(a) as minimum, max(b) as maximum 
  from test where id = pid; 

  return oResult; 
end; 
$$ language plpgsql;

结果

aadb=# select * from maxmin(2);
          minimum           |          maximum
----------------------------+----------------------------
 2010-01-11 17:09:55.049781 | 2010-01-11 17:10:30.501781
(1 row)

嘿 - 谢谢,你解决了第一个问题。这是我自己的愚蠢错误!然而,问题2仍然存在。表中可能有多行具有相同的GaugeID - 我想要它们的最大和最小日期。如果我在函数外运行查询,它可以完美地工作。但在函数内部,它会跨表获取最大和最小值。 - Robert
你能提供一下相关行的数据集样本吗?在函数中运行查询没有什么特别的。查询处理器首先运行查询的FROM和WHERE部分,因此必须根据WHERE子句限制结果。你确定你的函数已经更新了吗?/df+函数名称。 - Arthur Thomas
哦,我刚用 LANGUAGE 'SQL' STABLE 重写了这个函数;现在它完美地运行了。这一定是我做错了什么与 plpgsql 相关的事情... - Robert
嗯,STABLE不应该影响它。我只是不确定发生了什么。我把所有的测试条件都放进去了,对我来说一切都正常工作。不过很高兴你把它搞定了。 - Arthur Thomas
哦,你在执行'create or replace function...'之后pgadmin是否提交了?你的函数当前定义是什么呢 :) 我已经没有更多的想法了,呵呵。 - Arthur Thomas
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接