2015-05-31 42 views
3

我正在处理两个PostgreSQL同时安装:我的本地环境和真正的远程服务器。可悲的是服务器有一个旧版本(8.3.11),我的本地环境更新(9.4)。这两个PostgreSQL函数是否相同? (RETURNS TABLE和RETURNS SETOF)

我目前没有更新远程服务器的方法,因此我将一个运行良好的函数(它使用RETURNS TABLE)转换为8.3.11中应该没问题的函数(它应该使用RETURNS SETOF)。

不过,虽然当地的环境功能运作良好,并提供了良好的效果,遥控一个总是产生任何结果(使用同样的表!)

那么,这两个完全等同?对当地环境

较新的功能:

CREATE OR REPLACE FUNCTION pra2.GetGamesOnDate(date) 
    RETURNS TABLE (game_date date, is_home varchar, is_away varchar) AS $$ 
BEGIN 
    RETURN QUERY 
    SELECT g.game_date, p1.team_name AS plays_at_home, p2.team_name AS plays_away 
    FROM pra2.game g 
    JOIN pra2.team p1 ON g.is_home = p1.team_id 
    JOIN pra2.team p2 ON g.is_away = p2.team_id 
    WHERE g.game_date = $1; 
    IF NOT FOUND THEN 
     RAISE EXCEPTION 'No hay partidos para la fecha %.', $1; 
    END IF; 
    RETURN; 
END 
$$ 
    LANGUAGE plpgsql; 

这里的功能我已经修改使用SETOF

CREATE TYPE return_type AS 
(game_date date, 
is_home varchar, 
is_away varchar); 

CREATE OR REPLACE FUNCTION pra2.GetGamesOnDate(date) 
    RETURNS SETOF return_type AS $$ 
DECLARE 
    _rec return_type; 
BEGIN 
    RETURN QUERY 
    SELECT g.game_date, p1.team_name AS plays_at_home, p2.team_name AS plays_away 
    FROM pra2.game g 
    JOIN pra2.team p1 ON g.is_home = p1.team_id 
    JOIN pra2.team p2 ON g.is_away = p2.team_id 
    WHERE g.game_date = $1; 
    IF NOT FOUND THEN 
    RAISE EXCEPTION 'No hay partidos para la fecha %.', $1; 
    END IF; 
     RETURN next _rec; 
END 
$$ 
    LANGUAGE plpgsql; 

它没有给出错误信息的话,那运行正常,但它不会产生任何结果(它总是会引发异常消息),所以我想知道是否在中设置了错误查询...

+0

您忘了添加您提到的(逐字)错误消息。应该永远在那里。 –

回答

3

从文档判断,RETURN QUERY未在PostgreSQL 8.3中设置FOUND。 (PostgreSQL 9.1的相关文档位于http://www.postgresql.org/docs/9.1/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-DIAGNOSTICS;相应的语句没有出现在http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-DIAGNOSTICS的相应PostgreSQL 8.3文档中。)因此,您的IF NOT FOUND检查没有按照您的要求进行。

说实话,我不确定在PostgreSQL 8.3中完成此操作的最佳方法是什么。一种选择是写的是这样的:

CREATE OR REPLACE FUNCTION pra2.GetGamesOnDate(date) 
RETURNS SETOF return_type AS $$ 
DECLARE _rec return_type; 
     has_rec boolean; 
BEGIN 
    has_rec := false; 
    FOR _rec IN 
     SELECT g.game_date, p1.team_name AS plays_at_home, p2.team_name AS plays_away 
     FROM pra2.game g 
     JOIN pra2.team p1 ON g.is_home = p1.team_id 
     JOIN pra2.team p2 ON g.is_away = p2.team_id 
     WHERE g.game_date = $1 
    LOOP 
     has_rec := true; 
     RETURN NEXT _rec; 
    END LOOP; 
    IF NOT has_rec THEN 
     RAISE EXCEPTION 'No hay partidos para la fecha %.', $1; 
    END IF; 
END 
$$ LANGUAGE plpgsql; 

(免责声明:没有测试)

+0

高手!它完全像你说的那样工作!我仍然会抱怨他们正在使用8.3的事实......但至少你给了我很大的推动力。我最近才开始学习postgreSQL,并且通过阅读更新版本的文档来完成它,所以这有点令人困惑。 –

1

PL/pgSQL的does not set the special variable FOUND for RETURN QUERY in PostgreSQL 8.3,但。那是added with Postgres 8.4

但是,您仍然不必诉诸更复杂,更昂贵的循环。您可以使用其他方法GET DIAGNOSTICS _ct = ROW_COUNT;,它的说明书中的说明旁边FOUND

CREATE TYPE return_type AS (...); 

CREATE OR REPLACE FUNCTION pra2.GetGamesOnDate(date) 
    RETURNS SETOF return_type AS 
$func$ 
DECLARE 
    _ct int; 
BEGIN 
    RETURN QUERY 
    SELECT g.game_date, p1.team_name, p2.team_name 
    FROM pra2.game g 
    JOIN pra2.team p1 ON g.is_home = p1.team_id 
    JOIN pra2.team p2 ON g.is_away = p2.team_id 
    WHERE g.game_date = $1; 

    GET DIAGNOSTICS _ct = ROW_COUNT; -- number of returned rows. 

    IF _ct = 0 THEN 
     RAISE EXCEPTION 'No hay partidos para la fecha %.', $1; 
    END IF; 
END 
$func$ LANGUAGE plpgsql; 

而且,你的变量_rec return_typeRETURN next _rec;没有任何作用在原始版本。

现在这个功能是等价的。你甚至可以在Postgres 9.4中使用它。

与此密切相关的答案:

旁白:骆驼个案标识像 GetGamesOnDate 是Postgres的一个坏主意。坚持合法的小写字母名称。

+0

感谢您的替代版本,我会记住你的建议! –