Postgres存储过程/函数

时间:2017-10-03 15:29:04

标签: postgresql stored-procedures

存储过程的新功能,需要在存储过程中执行多个查询并返回结果。我想知道这是否可能。

Ex:  查询1返回用户标识列表..  从user =?

的用户中选择userid

对于上述查询中的每个用户标识,我需要执行三个不同的查询,例如 查询2从sessionid中选择session_details,其中userid =? 查询3从userid =?

的位置选择位置

返回值应该是session_details和location的集合。

这可能,你能提供一些提示吗?

3 个答案:

答案 0 :(得分:0)

完全基于您的示例,这可能是最简单的方法:

CREATE FUNCTION my_func(user_id INTEGER)
  RETURNS TABLE (userid INTEGER, session INTEGER, location TEXT) AS
$$
    SELECT u.userid, s.session, l.location
    FROM -- etc... your query here
$$ 
  LANGUAGE SQL STABLE;

发表评论: 这是一个不同的问题。一个问题是如何在存储过程中返回包含多个字段的多个记录。一种方法如上。

另一个问题是如何编写从多个表中获取数据的查询。同样,有很多方法可以做到这一点。一种方法是(再次,基于我对示例中的要求的解释):

SELECT  userid
,   ARRAY_AGG(SELECT session_details FROM session s WHERE s.userid = u.userid)
,   ARRAY_AGG(SELECT l.location FROM location l WHERE l.userid = u.userid)
FROM user u
WHERE username = user_name

这将返回一条记录,其中包含user_id,该用户的session_details数组以及该用户的位置数组。

然后该功能可以更改为:

CREATE FUNCTION my_func(user_name TEXT, OUT userid INTEGER, OUT session_details TEXT[], OUT locations TEXT[])
  AS $$
    SELECT  userid
    ,   ARRAY(SELECT session_details FROM session s WHERE s.userid = u.userid)
    ,   ARRAY(SELECT l.location FROM location l WHERE l.userid = u.userid)
    FROM user u
    WHERE username = user_name;
$$ LANGUAGE SQL STABLE;

答案 1 :(得分:0)

您可以像这样遍历查询结果:

FOR id IN   Select userid from user where username = ?
LOOP

...
 END LOOP;

答案 2 :(得分:0)

正如@Fahad Anjum在评论中所说,如果你能在查询中做到这一点,那就更好了。但如果这不可行,那么你就有了树的可能性来实现你想要的东西。

  1. SETOF
  2. REFCURSOR
  3. <强> 1。 SETOF

    您可以返回一组值。该集可以是现有表,时态表或您定义的TYPE。

    TYPE示例:

    -- In your case the type could be (userid integer, session integer, location text)
    CREATE TYPE tester AS (id integer);
    -- The pl returns a SETOF the created type.
    CREATE OR REPLACE FUNCTION test() RETURNS SETOF tester
    AS $$
    BEGIN
        RETURN QUERY SELECT generate_series(1, 3) as id;
    END;
    $$ LANGUAGE plpgsql
    -- Then, you get the set by selecting the PL as if it were a table.
    SELECT * FROM test();
    

    表格和临时表格示例:

    -- Create a temporal table o a regular table:
    CREATE TEMP TABLE test_table(id integer);
    -- or CREATE TABLE test_table(id integer);
    -- or use an existing table in your schema(s);
    -- The pl returns a SETOF the table you need
    CREATE OR REPLACE FUNCTION test() RETURNS SETOF test_table
    AS $$
    BEGIN
        RETURN QUERY SELECT  generate_series(1, 3) as id;
    END;
    $$ LANGUAGE plpgsql
    -- Then, you get the set by selecting the PL as if it were a table.
    SELECT * FROM test();
    -- NOTE: Since you are only returning a SETOF the table,
    -- you don't insert any data into the table.
    -- So, if you select the 'temp' table you won't see any changes.
    SELECT * FROM test_table
    

    <强> 2。表

    PL可以返回一个表,它类似于创建一个临时表,然后返回一个SETOF,但是,在这种情况下,你声明de&#39; temp&#39;关于&#39;表的回复&#39; PL的句子。

    -- Next to TABLE you define the columns of the table the PL will return
    CREATE OR REPLACE FUNCTION test() RETURNS TABLE (id integer)
    AS $$
    BEGIN
        RETURN QUERY SELECT  generate_series(1, 3) as id;
    END;
    $$ LANGUAGE plpgsql
    -- As the other examples, you select the PL to get the data.
    SELECT * FROM test();
    

    第3。 REFCURSOR

    这是更复杂的解决方案。您返回游标,而不是实际数据。如果你需要动态的&#39;返回集合的值,这是解决方案。

    但由于您需要静态数据,因此您不需要此选项。

    使用任何这些方式取决于任何特定情况,如果您经常使用不同方式的用户ID,会话,位置和PL,最好使用带有类型的SETOF。

    如果您的表具有userid,session,location列,则最好返回SETOF表。

    如果你只使用一个案例的用户ID,会话,位置,那么最好使用&#39; RETURNS TABLE&#39;方法

    如果您需要返回一个动态集,则必须使用游标......但该解决方案确实更先进。