Синтаксис Posgre SQL - l oop - PullRequest
       6

Синтаксис Posgre SQL - l oop

0 голосов
/ 19 февраля 2020

У меня есть следующее l oop (упрощенно для примера):

DO $$
  DECLARE
    l record;

  BEGIN
    FOR l IN SELECT id, country_id FROM logo LOOP
      WITH cs AS (
        INSERT INTO logo_settings (targeted) VALUES (true)
        RETURNING id
      )
      INSERT INTO logo_settings_targeted (logo_settings_id, country_id)
      VALUES 
      ( (SELECT id FROM cs),
        logo.country_id,
      );
    END LOOP;
  END;
END $$;

Тело al oop работает нормально. Но если я оберну его в al oop (я хотел бы сделать записи для всех записей из таблицы lo go) - он выдаст сообщение об ошибке:

ERROR: syntax error at or near "END"
  Position: 712

END;
^

, означающее последний EnND перед END $$; что не имеет большого смысла для меня. Я не знаю, что исправить, чтобы он работал. Есть намеки?

Ответы [ 2 ]

2 голосов
/ 19 февраля 2020

Существует один end для многих. end loop закрывает тело l oop:

DO $$
  DECLARE
    l record;

  BEGIN
    FOR l IN SELECT id, country_id FROM logo LOOP
      WITH cs AS (
        INSERT INTO logo_settings (targeted) VALUES (true)
        RETURNING id
      )
      INSERT INTO logo_settings_targeted (logo_settings_id, country_id)
      VALUES 
      ( (SELECT id FROM cs),
        logo.country_id,
      );
    END LOOP;
  END $$;
1 голос
/ 19 февраля 2020

Дополнительно к ответу @Andronicus, это один из возможных способов сделать это без PL / pg sql:

Нажмите: demo: db <> fiddle

WITH countries AS  (
    SELECT id, country_id, 
        row_number() OVER ()                                        -- 1
    FROM logo
), ins_settings AS (
    INSERT INTO logo_settings(targeted)
    SELECT true FROM countries c
    RETURNING id
)
INSERT INTO logo_settings_targeted (logo_settings_id, country_id)
SELECT
  ins.id, c.country_id
FROM
  (SELECT id, row_number() OVER () FROM ins_settings) ins            -- 2
JOIN countries c ON c.row_number = ins.row_number
  1. Поместите первый запрос SELECT (который вы использовали для l oop) во второй CTE вверху.
  2. Хитрость в том, что вы можете объединить выходы из оператора logo SELECT и первой вставки. Вы можете использовать тот факт, что оба выхода имеют одинаковое количество строк. Просто добавьте столбец с количеством строк к обоим выходам. Это можно сделать, например, с помощью оконной функции row_number() . Как видите, для logo SELECT я уже сделал это непосредственно в CTE (1), для вывода INSERT я добавил это в подзапросе (2). Теперь в обеих таблицах есть одинаковые идентификаторы, которые можно использовать для объединения.
  3. Объединение является основой для второго INSERT.
...