PostgreSQL - 将数组传递给存储函数

时间:2016-02-04 21:39:50

标签: sql postgresql stored-procedures

我有两个独立的数据库(MySQL和PostgreSQL),它们可以维护组织中不同部门的不同数据集 - 这是无法更改的。我需要连接到一个来获取第一个数据库中symbolsids的列表,并在python中使用DBAPI,并请求另一个集合并对其进行操作。

(我花了很多时间在这种方法上,因为我的架构中的其他组件是有意义的,所以除非有更好的替代方案,否则我想坚持下去用这种方法。)

CREATE TABLE foo (fooid int, foosubid int, fooname text);
INSERT INTO foo VALUES (1, 1, 'Joe');
INSERT INTO foo VALUES (1, 2, 'Ed');
INSERT INTO foo VALUES (2, 1, 'Mary');

CREATE FUNCTION get_results(text[]) RETURNS SETOF record AS $$
SELECT fooname, fooid, foosubid FROM foo WHERE name IN $1;
$$ LANGUAGE SQL;

实际上我的SQL要复杂得多,但我认为这种方法完全描述了目的。 我可以将任意长度参数传入存储过程或用户定义函数并返回结果集吗?

我想把这个函数称为:

SELECT * FROM get_results(('Joe', 'Ed'));
SELECT * FROM get_results(('Joe', 'Mary'));
SELECT * FROM get_results(('Ed'));

我相信使用IN并传递这些参数(如果可能的话)会给我与JOIN相同(或相当)的表现。对于我目前的用例,符号不会超过750-1000'名称',但如果性能是一个问题,我也想知道原因。

3 个答案:

答案 0 :(得分:2)

Row vs Array构造函数

('Joe', 'Ed')相当于ROW('Joe', 'Ed')并创建一个新行。

但是你的函数接受一个数组。要创建一个,请使用Array构造函数调用它:

SELECT * FROM get_results(ARRAY['Joe', 'Ed']);

可变函数

您可以将输入参数声明为VARIADIC,如此

CREATE FUNCTION get_results(VARIADIC text[]) RETURNS SETOF record AS $$
SELECT fooname, fooid, foosubid FROM foo WHERE name = ANY($1);
$$ LANGUAGE SQL;

它接受可变数量的参数。你可以这样称呼它:

SELECT * FROM get_results('Joe', 'Ed');

有关可变长度参数的函数的更多信息:http://www.postgresql.org/docs/9.4/static/xfunc-sql.html

答案 1 :(得分:1)

贾里德, 如果只想将数组传递给where子句中的过程或函数调用,可以尝试使用:

CREATE FUNCTION get_results(text[]) RETURNS SETOF record AS $$
SELECT fooname, fooid, foosubid FROM foo WHERE name = any($1);
$$ LANGUAGE SQL;

答案 2 :(得分:1)

使用RETURNS TABLE代替RETURNS SETOF record。这将简化函数调用。

您不能以这种方式使用IN运算符。请改用ANY

CREATE FUNCTION get_results(text[]) 
RETURNS TABLE (fooname text, fooid int, foosubid int) 
AS $$
    SELECT fooname, fooid, foosubid 
    FROM foo 
    WHERE fooname = ANY($1);
$$ LANGUAGE SQL;

SELECT * FROM get_results(ARRAY['Joe']);

 fooname | fooid | foosubid 
---------+-------+----------
 Joe     |     1 |        1
(1 row)

如果函数返回setof记录,则必须在每个函数调用中放置一个列定义列表:

SELECT * 
FROM get_results(ARRAY['Joe']) AS (fooname text, fooid int, foosubid int)