Записи курсор в PostgreSQL
Я пытаюсь использовать курсор для запроса, объединяющего несколько таблиц. Я видел, что для 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
2 ответов
просто использовать RECORD
тип:
DECLARE
...
cur_row RECORD;
BEGIN
...
FETCH xyz INTO cur_row;
EXIT WHEN NOT FOUND;
IF cur_row.city LIKE 'CH%' THEN
...
1. Неявный курсор
почти всегда лучше использовать неявный курсор FOR
цикл чем прибегать к несколько более медленному и громоздкому явному курсору. Я написал тысячи функций 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;
в сторону: в функции нет ничего, что нуждалось бы волатильность VOLATILE
. Использовать STABLE
.
2. Set-based подходи!--8-->
почти всегда лучше использовать подход на основе набора если это возможно. Использовать 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 или даже просто запрос:
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;