PostgreSQL RETURN NEXT error "возвращено более одной строки" - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть длинная функция PGPLSQL: вот краткое изложение

CREATE FUNCTION get_features_by_buffer(
                    p_buffer GEOMETRY
                )
RETURNS SETOF JSON AS $BODY$
    DECLARE
        v_buffer GEOMETRY;
        v_sql TEXT
    BEGIN
    FOR REC IN EXECUTE $$(
                (
                    SELECT row_to_json(foo_pole) AS json FROM 
                       (
                         SELECT * FROM pole WHERE $$ || v_sql_where || $$
                       ) AS foo_pole
                 )
                 UNION ALL 
                 (
                    SELECT row_to_json(foo_transformerbank) AS json FROM 
                       (
                         SELECT * FROM transformerbank WHERE $$ || v_sql_where || $$) AS foo_transformerbank
                       )
                 )$$ LOOP
        RETURN NEXT REC.json;
    END LOOP;
    END
$BODY$
LANGUAGE plpgsql;

Моя функция возвращает RETURNS SETOF JSON, и это немного сложнее, чем показано здесь, однако я выполнил запросы, которые находятся внутри оператора UNION ALL, и нет синтаксиса или другой ошибки. Здесь это выглядит странно, потому что я возился, но сначала попробовал, поместив оператор запроса в v_sql и выполнив RETURN QUERY EXECUTE v_sql, что также дает ту же ошибку, что и версия, показанная здесь. Ошибка выглядит следующим образом:

ОШИБКА: запрос «SELECT get_features_by_buffer (v_buffer)» вернул более одной строки
КОНТЕКСТ: PL / pgSQL функция get_features_by_pole_distance (изменение символов, двойная точность) строка 7 при ВОЗВРАЩЕНИИ СЛЕДУЮЩАЯ

Я какое-то время возился с этим, не уверен, что мне здесь не хватает, что-то связанное с UNION ALL?

1 Ответ

0 голосов
/ 04 сентября 2018

Насколько я могу судить, вам не нужен курсор. Просто используйте сгенерированный SQL в качестве ввода для return query execute ...:

Также проще генерировать динамический SQL с помощью функции format():

CREATE FUNCTION get_features_by_buffer(p_buffer GEOMETRY)
   RETURNS SETOF JSON 
AS 
$BODY$
DECLARE
    v_buffer GEOMETRY;
    v_sql TEXT
BEGIN
  RETURN QUERY EXECUTE 
    format(
      'SELECT row_to_json(foo_pole) AS json 
      FROM (
        SELECT * 
        FROM pole 
        WHERE %s
      ) AS foo_pole
      UNION ALL 
      SELECT row_to_json(foo_transformerbank) AS json 
      FROM (
        SELECT * 
        FROM transformerbank 
        WHERE %s
      ) AS foo_transformerbank', v_sql_where, v_sql_where);
 END
$BODY$
LANGUAGE plpgsql;

Поскольку эта функция объявлена ​​как returns setof, вы должны использовать ее как таблицу:

select * 
from get_features_by_buffer(...);
...