【问题标题】:Cursor based records in PostgreSQLPostgreSQL 中基于游标的记录
【发布时间】:2014-04-15 21:15:11
【问题描述】:

我正在尝试将游标用于连接多个表的查询。我已经看到对于 oracle 有一个基于游标的记录。当我为 Postgres 尝试相同的操作时,它会引发一些错误。我怎样才能在 Postgres 中做同样的事情?

CREATE OR REPLACE FUNCTION avoidable_states()
RETURNS SETOF varchar AS
$BODY$
DECLARE
    xyz CURSOR FOR select * from address ad
                            join city ct on ad.city_id = ct.city_id;    
    xyz_row RECORD;
BEGIN   
    open xyz;

    LOOP
    fetch xyz into xyz_row;
        exit when xyz_row = null;
        if xyz_row.city like '%hi%' then
            return next xyz_row.city;               
        end if;
    END LOOP;
    close xyz;  
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

我得到的错误是:

ERROR:  relation "xyz" does not exist
CONTEXT:  compilation of PL/pgSQL function "avoidable_states" near line 4

【问题讨论】:

    标签: postgresql loops plpgsql database-cursor


    【解决方案1】:

    只需使用RECORD 类型:

    DECLARE
        ...
        cur_row RECORD;
    BEGIN
        ...
        FETCH xyz INTO cur_row;
        EXIT WHEN NOT FOUND;
        IF cur_row.city LIKE 'CH%' THEN
            ...
    

    【讨论】:

    • 感谢工作。但是,在循环中,我如何跳出循环?说我在 cur_row = null 时使用了退出;它不会爆发。我用新代码更新了原始问题。
    • @Zeus,我更新了答案以显示您想要的内容。请参阅 Erwin 的回答,因为它向您展示了一些其他(并且通常是更好的恕我直言)迭代查询的方法,尽管有时我们确实需要一个游标,所以...
    【解决方案2】:

    1。隐式游标

    使用FOR loop 的隐式游标几乎总是比使用更慢且笨拙的显式游标更好。我已经编写了数千个 plpgsql 函数,但只有一堆显式游标才有意义。

    CREATE OR REPLACE FUNCTION avoidable_states()
      RETURNS SETOF varchar AS
    $func$
    DECLARE
        rec record;
    BEGIN   
       FOR rec IN
          SELECT *
          FROM   address ad
          JOIN   city    ct USING (city_id)
       LOOP
          IF rec.city LIKE '%hi%' THEN
              RETURN NEXT rec.city;               
          END IF;
       END LOOP;
    END
    $func$  LANGUAGE plpgsql STABLE;
    

    除此之外:函数中没有任何东西需要volatility VOLATILE。使用STABLE

    2。基于集合的方法

    使用基于集合的方法几乎总是更好如果可能。使用RETURN QUERY 直接从查询返回。

    CREATE OR REPLACE FUNCTION avoidable_states()
      RETURNS SETOF varchar AS
    $func$
    BEGIN   
       RETURN QUERY
       SELECT ct.city
       FROM   address ad
       JOIN   city    ct USING (city_id)
       WHERE  ct.city LIKE '%hi%';
    END
    $func$  LANGUAGE plpgsql STABLE;
    

    3。 SQL函数

    对于简单的情况(可能是简化),您还可以使用简单的SQL function 甚至只是查询:

    CREATE OR REPLACE FUNCTION avoidable_states()
      RETURNS SETOF varchar AS
    $func$
       SELECT ct.city
       FROM   address ad
       JOIN   city    ct USING (city_id)
       WHERE  ct.city LIKE '%hi%';
    $func$  LANGUAGE sql STABLE;
    

    【讨论】:

    • 我来自 Oracle PL/SQL 背景,我想知道是否有办法“隐藏”函数的 DECLARE 部分中的隐式光标,然后仅引用它通过 FOR 循环中的光标名称?当然,当您的选择语句只有几行代码时,它并没有太大的区别。但是如果SELECT 语句是 50 行代码,那么必须在过程代码中包含 SQL 确实会分散注意力(出于调试目的)。
    猜你喜欢
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    • 2017-02-28
    相关资源
    最近更新 更多