Postgres 游标惰性求值

问题描述 投票:0回答:1

我正在尝试从 Oracle 复制一个具有以下代码片段的函数

OPEN pcursor FOR v_sql;
        loop
            fetch pcursor into
                out_rec.XYZ
            ;

            exit when pcursor%NOTFOUND;

                     INSERT INTO tab1 VALUES (out_rec.XYZ);
                     COMMIT;
            pipe row(out_rec);
        end loop;
EXCEPTION
        WHEN OTHERS THEN
            v_err_code := SQLCODE;

存储在 v_sql 中的查询存在一个问题,对于某些特定行值,它无法执行。 IE。在 SQL Developer 中,如果我执行查询,它会返回一些数据,但如果我将结果集获取到末尾或对其执行 count(*) 操作,则会失败,因为查询中的值之一返回错误数据。该错误无关紧要,但该函数的行为是它返回数据,直到到达错误点,然后完成。数据不完整(不会返回错误点之外的任何行),但数据确实存在。这是因为异常处理子句实际上并没有做任何事情(它吞噬了异常)

现在,当我尝试在 PostgreSQL 中复制此内容时,我遇到了几个问题。

  1. 我无法找出延迟执行查询的方法。当我执行它时 - 无论我是否获取所有数据,它都会失败。
  2. 我创建了以下代码来模拟光标的行为
CREATE OR REPLACE FUNCTION test_fn()
 RETURNS table (t ret_data_type)
 LANGUAGE plpgsql
AS $function$
...
for t in execute v_sql
    loop
        return next;
    end loop;
    exception when others then
        raise notice 'error';
...

这对于没有错误的数据运行良好,但如果整个数据集中有任何错误,它就会失败并且不返回任何数据集。

我的问题是:有没有办法让 Postgresql 惰性地评估游标(一次几行)并继续返回数据,直到遇到错误?我正在查看文档,但没有看到任何内容。

postgresql oracle
1个回答
0
投票

看起来 PG 在循环之前获取了所有数据

它没有 - cursors 的要点之一是 not 正是这样做的。没有太多需要添加的@Frank Heikens'立即响应:如果您希望它继续,请将异常处理放在循环内。
db-fiddle 的演示

create table test as select '{"a":"b"}'::text t from generate_series(1,1e5);
insert into test select '{a:1}';--that's not a valid json/jsonb
insert into test select '{"a":"b"}'::text from generate_series(1,1e5);

create or replace function f()returns table(j jsonb) as $f$
declare rec record;
begin 
  for rec in select t from test loop 
  begin j:=rec.t; return next;
  exception when others then raise notice '% ignored',rec.t;
  end;
end loop;
end$f$language plpgsql;

create table test2 as select f();
NOTICE:  {a:1} ignored
SELECT 200000

即使输入表中间有一个无效的

json
,处理/忽略循环内的异常也可以让您继续。

我确实尝试过,但没有帮助

处理或忽略错误后,在整个函数末尾处理

exception
将终止该函数。如果您将其向内移动到循环中并在
begin..exception..end
周围添加一个
return next
,这仍然不起作用,因为异常可能会在上面的
for t in execute v_sql
中的赋值中抛出。您必须显示您的实际代码才能确定。

© www.soinside.com 2019 - 2024. All rights reserved.