Postgresql

时间:2015-12-28 14:44:32

标签: postgresql dynamic cursor plpgsql

我有一个光标,它指向一个SELECT,但是这个选择是动态生成的。我想在声明后分配声明。 我做了一个工作的例子,另一个例子不工作。这是仅打印一些数据的简单示例。 这是表格:

CREATE TABLE public.my_columns (
  id      serial NOT NULL,
  "name"  varchar(30) NOT NULL,
  /* Keys */
  CONSTRAINT my_columns_pkey
    PRIMARY KEY (id)
) WITH (
    OIDS = FALSE
  );

CREATE INDEX my_columns_index01
  ON public.my_columns
  ("name");


INSERT INTO public.my_columns
    ("name")
VALUES
    ('name1'),
    ('name2'),
    ('name3'),
    ('name4'),
    ('name5'),
    ('name6');

这是函数(我已将工作代码和代码无效):

CREATE OR REPLACE FUNCTION public.dynamic_table
(
)
RETURNS text AS $$
DECLARE
       v_sql_dynamic varchar;

       --NOT WORKING:
       --db_c CURSOR IS (v_sql_dynamic::varchar);

       --WORKING:
       db_c CURSOR IS (SELECT id, name from public.my_columns);

       db_rec RECORD;

BEGIN
     v_sql_dynamic := 'SELECT id, name from public.my_columns';
    FOR db_rec IN db_c LOOP

        RAISE NOTICE 'NAME: %', db_rec.name;
    END LOOP;
    RETURN 'OK';

EXCEPTION WHEN others THEN

    RETURN 'Error: ' || SQLERRM::text || ' ' || SQLSTATE::text;
END; 
$$ LANGUAGE plpgsql;

有什么想法吗?

谢谢。

1 个答案:

答案 0 :(得分:7)

你真的需要显式游标吗?如果需要迭代动态SQL,则可以使用FOR IN EXECUTE。它是用于动态SQL的隐式(内部)游标的循环

FOR db_rec IN EXECUTE v_sql_dynamic
LOOP
  ..
END LOOP

documentation - OPEN FOR EXECUTE中描述了更复杂的解决方案:

do $$
declare r refcursor; rec record;
begin 
  open r for execute 'select * from pg_class'; 
  fetch next from r into rec;
  while found 
  loop
    raise notice '%', rec; 
    fetch next from r into rec; 
  end loop;
  close r; 
end $$;

使用这种光标,您无法使用FOR IN