PL/pgSQL 中的光标
Posted
技术标签:
【中文标题】PL/pgSQL 中的光标【英文标题】:Cursor in PL/pgSQL 【发布时间】:2016-06-04 12:32:52 【问题描述】:我想在函数中使用游标,但我在定义一个变量时出错,请查看并帮助:)
CREATE OR REPLACE FUNCTION curson_func (
start_date timestamp,
end_date timestamp)
RETURNS SETOF integer AS $$
DECLARE
level_cursor CURSOR FOR
SELECT
login_event.player_id,
registration.country_id
FROM
"fish-tsg".registration
LEFT JOIN
"fish-tsg".login_event USING (player_id)
WHERE
ts >= start_date AND ts <= end_date ;
level_cursor_row "fish-tsg".login_event%ROW_TYPE;
BEGIN
OPEN level_cursor;
LOOP FETCH level_cursor INTO level_cursor_row;
EXIT WHEN level_cursor_row = null;
END LOOP;
CLOSE level_cursor;
RETURN level_cursor_row;
END $$
LANGUAGE 'plpgsql';
我得到的错误:
ERROR: invalid type name ""fish-tsg".login_event%ROW_TYPE"
LINE 20: level_cursor_row "fish-tsg".login_event%ROW_TYPE;
【问题讨论】:
Copying Types 另外还有与使用游标相关的错误。以this tutorial 为例。 【参考方案1】:您使用的是哪个版本的 PostgreSQL?您的语法(除了代码中的许多错误)是非常古老的风格,现在更容易了。例如:
CREATE OR REPLACE FUNCTION cursor_func (_start_date timestamp, _end_date timestamp) RETURNS TABLE (player_id int, country_id int) AS $BODY$
DECLARE
_level record;
BEGIN
FOR _level IN -- cursor is opened automatically
SELECT login_event.player_id, registration.country_id
FROM "fish-tsg".registration
LEFT JOIN "fish-tsg".login_event USING (player_id)
WHERE ts BETWEEN _start_date AND _end_date
LOOP
RETURN NEXT _level;
END LOOP;
-- note that cursor is auto-closed
RETURN;
END;
$BODY$ LANGUAGE plpgsql;
但您可能会从根本没有光标的更简单的方法中受益:
CREATE OR REPLACE FUNCTION cursor_func (_start_date timestamp, _end_date timestamp) RETURNS TABLE (player_id int, country_id int) AS $BODY$
BEGIN
RETURN QUERY
SELECT login_event.player_id, registration.country_id
FROM "fish-tsg".registration
LEFT JOIN "fish-tsg".login_event USING (player_id)
WHERE ts BETWEEN _start_date AND _end_date;
RETURN;
END;
$BODY$ LANGUAGE plpgsql;
甚至更简单:
CREATE OR REPLACE FUNCTION cursor_func (_start_date timestamp, _end_date timestamp) RETURNS TABLE (player_id int, country_id int) AS $BODY$
SELECT login_event.player_id, registration.country_id
FROM "fish-tsg".registration
LEFT JOIN "fish-tsg".login_event USING (player_id)
WHERE ts BETWEEN $1 AND $2
$BODY$ LANGUAGE sql;
【讨论】:
【参考方案2】:我有新的东西,但我收到只有一行。问题出在哪里?
CREATE OR REPLACE FUNCTION bi.temp_cursor()
RETURNS refcursor AS
$BODY$
DECLARE
ref refcursor;
ref2 RECORD;
BEGIN
OPEN ref FOR SELECT player_id, ts FROM "fish-tsg".registration LIMIT 100;
FETCH ref INTO ref2;
LOOP
RETURN ref2;
EXIT WHEN NOT FOUND;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;
SQL 查询是示例,问题是 pl/pgsql 中的游标
【讨论】:
【参考方案3】:也许更好的方法是使用视图而不是函数。
首先,创建一个视图:
CREATE VIEW temp_view
as
SELECT
login_event.player_id,
registration.country_id,
ts
FROM "fish-tsg".registration
LEFT JOIN "fish-tsg".login_event USING (player_id)
然后,使用通常放置表名的视图名执行普通选择:
select player_id, country_id
from temp_view
where ts between $start_date AND $end_date;
【讨论】:
以上是关于PL/pgSQL 中的光标的主要内容,如果未能解决你的问题,请参考以下文章