在 Postgresql 中动态生成的 CURSOR
Dynamically generated CURSOR in Postgresql
我有一个光标,它指向一个 SELECT,但是这个 select 是动态生成的。我想在声明之后分配声明。
我已经完成了一个工作示例和另一个不工作的示例。这是一个仅打印一些数据的简单示例。
这是 table:
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;
有什么想法吗?
谢谢。
你真的需要显式游标吗?如果您需要迭代动态 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
我有一个光标,它指向一个 SELECT,但是这个 select 是动态生成的。我想在声明之后分配声明。 我已经完成了一个工作示例和另一个不工作的示例。这是一个仅打印一些数据的简单示例。 这是 table:
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;
有什么想法吗?
谢谢。
你真的需要显式游标吗?如果您需要迭代动态 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