创建返回文本数组的函数

时间:2014-03-03 21:25:47

标签: sql postgresql stored-procedures plpgsql

我尝试创建一个函数,该函数将返回以下查询的内容,其中proto_location是text类型。不确定它是否重要,但我当前调用此查询的java代码只是将每条记录作为字符串读取。

SELECT DISTINCT tm.proto_location
FROM track_message tm
WHERE tm.workflow_analytic_instance_id = 204
AND EXISTS ( SELECT *
    FROM track_message_to_track_mapping tm2tm
    JOIN track t ON t.id = tm2tm.track_id
    JOIN track_item ti ON t.id = ti.track_id
    JOIN track_point tp ON ti.id = tp.track_item_id
    WHERE tm.id =tm2tm.track_message_id
    AND ti.item_time BETWEEN 1328816277089000 AND 1328816287089000
    AND ST_Intersects
            (tp.track_position
            , ST_GeomFromText('POLYGON((-144 59, -41 46, -75 15, -127 25, -144 59))',4326)
            )
    )
    ;

这是我的功能

CREATE OR REPLACE Function getTrackMessages(workflow bigint, start_time bigint, end_time bigint) returns text[]
as $$
SELECT DISTINCT tm.proto_location
FROM track_message tm
WHERE tm.workflow_analytic_instance_id = $1AND EXISTS ( SELECT *
    FROM track_message_to_track_mapping tm2tm
    JOIN track t ON t.id = tm2tm.track_id
    JOIN track_item ti ON t.id = ti.track_id
    JOIN track_point tp ON ti.id = tp.track_item_id
    WHERE tm.id =tm2tm.track_message_id
    AND ti.item_time BETWEEN $2 AND $3        AND ST_Intersects
            (tp.track_position
            , ST_GeomFromText('POLYGON((-144 59, -41 46, -75 15, -127 25, -144 59))',4326)
            )
    )
    ;
$$ Language 'plpgsql';

我一直收到一条错误,指出“select”或其附近的语法错误及其引用行

SELECT DISTINCT tm.proto_location

1 个答案:

答案 0 :(得分:3)

CREATE OR REPLACE FUNCTION get_track_messages(workflow bigint, start_time bigint, end_time bigint)
  RETURNS SETOF text[] AS
$func$

SELECT DISTINCT tm.proto_location
FROM   track_message tm
WHERE  tm.workflow_analytic_instance_id = $1
AND    EXISTS (
    SELECT *
    FROM   track_message_to_track_mapping tm2tm
    JOIN   track t ON t.id = tm2tm.track_id
    JOIN   track_item ti ON t.id = ti.track_id
    JOIN   track_point tp ON ti.id = tp.track_item_id
    WHERE  tm.id = tm2tm.track_message_id
    AND    ti.item_time BETWEEN $2 AND $3
    AND    ST_Intersects (tp.track_position
            , ST_GeomFromText('POLYGON((-144 59, -41 46, -75 15, -127 25, -144 59))',4326)
            )
    );
$func$ LANGUAGE sql;

最重要的是,它可以用作 sql 功能 对于PL / pgSQL函数,您需要更改:

CREATE OR REPLACE FUNCTION get_track_messages(workflow bigint
                                            , start_time bigint
                                            , end_time bigint)
  RETURNS SETOF text[] AS
$func$
BEGIN

RETURN QUERY
SELECT DISTINCT ... ;

END
$func$ LANGUAGE plpqsql;

如果查询返回的行数超过1行,您还需要SETOF(正如您自己想象的那样)。你需要调用函数:

SELECT * FROM get_track_messages( ... );

另请注明语言名称plpgsqlsql。它是一个标识符,而不是字符串。

More about returning from a function in the manual.

数据类型

如果proto_locationcharacter type,您可以这样汇总:

SELECT array_agg(DISTINCT tm.proto_location) ...

(实际上,您可以将array_agg()任何标量类型一起使用,但上面的函数定义为返回text[],因此您必须将其他类型转换为文本my_odd_column::text。)
或者对于排序数组:

SELECT array_agg(DISTINCT tm.proto_location ORDER BY proto_location) ...

或者,要获取排序列表(text)而不是数组(text[]):

SELECT string_agg(DISTINCT tm.proto_location ORDER BY proto_location, ', ') ...

更多信息:
How to use array_agg() for varchar[]
Alternatives to Array_Agg: PostgreSQL