Sql

For loop postgresql: postgresql — Postgres FOR LOOP

postgresql — Как использовать WITH в сочетании с циклом FOR в PLPGSQL?

Задавать вопрос

спросил

Изменено 2 года, 9 месяцев назад

Просмотрено 513 раз

Я хочу создать хранимую функцию, тело которой будет перебирать результаты оператора WITH. Это возможно? До сих пор я получаю синтаксические ошибки для FOR, который следует за WITH. Минимальный пример:

 DO $$
ОБЪЯВИТЬ loop_col1 RECORD;
НАЧИНАТЬ
    С temp_table КАК (
        ВЫБЕРИТЕ col1, col2 ИЗ файлов
    )
    FOR loop_col1 IN
        ВЫБЕРИТЕ ОТЛИЧНЫЙ col1 ОТ temp_table
    ПЕТЛЯ
        -- сделать что-то, используя все столбцы из temp_table
    КОНЕЦ ПЕТЛИ;
КОНЕЦ $$;
 

Причина, по которой я хочу зациклиться на столбце 1, заключается в том, что он группирует значения столбца 2, и для каждой группы значений я хочу поместить новые отношения в другую таблицу (например, часть «сделать что-то»)

Другие решения, которые позволяют мне иметь «временная таблица» данных тоже подойдет.

Полный запрос контекста приведен ниже. Посмотрите, как тело цикла несколько раз ссылается на таблицу WITH.

 СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ enqueue_postprocessing_jobs()
ВОЗВРАЩАЕТ пустоту
ЯЗЫК plpgsql КАК $$
ЗАЯВИТЬ
    loop_group_uufid ЗАПИСЬ;
    loop_uurid ЗАПИСЬ;
НАЧИНАТЬ
    -- 1. Найдите информацию о файлах, которые можно использовать для новой постобработки.
    -- работа. Результатом запроса являются все файлы, связанные с заданиями постобработки.
    С файлами_кандидатов_постобработки_файлов
    ВЫБЕРИТЕ uufid, uurid, источник, group_uufid
    ИЗ файлов
    ГДЕ источник = «ТРЕЩИНЫ» ИЛИ источник = «ФОН»
    И ууфид НЕ ВО(
        -- Найти все файлы, с которыми связано задание
        ВЫБЕРИТЕ ОТЛИЧНЫЕ uufid ОТ get_files_and_jobs()
        ГДЕ тип = 'ПОСТОБРАБОТКА'
    )
    -- 2. Сгруппируйте файлы-кандидаты по group_uufid (a) и просмотрите их, чтобы проверить,
    -- имеются все необходимые файлы (b), если да, вставьте новое задание (c) и
    -- подключить работу к файлам (d)
    ДЛЯ loop_group_uufid В
        ВЫБЕРИТЕ РАЗЛИЧНЫЕ group_uufid
        ИЗ файлов_кандидатов_постобработки
    ПЕТЛЯ
        -- а.
Сделать повторно используемую временную таблицу только с файлами этой группы С group_postprocessing_files AS ( ВЫБЕРИТЕ * ИЗ файлов_кандидатов_постобработки ГДЕ group_uufid=loop_group_uufid ), -- б. Выберите идентификаторы этих файлов и запустите, где все необходимые файлы -- подарок. Результаты запроса в таблице имеют длину 0 строк, если не все файлы -- присутствуют для этого задания, в противном случае оно должно состоять из 2 строк. -- Один ряд для трещин, один ряд для фона. -- Другими словами, вся эта таблица функционирует как один кандидат на работу. job_candidate КАК ( ВЫБЕРИТЕ uufid, uurid ИЗ group_postprocessing_files ГДЕ «ТРЕЩИНЫ» В (ВЫБЕРИТЕ источник ИЗ group_postprocessing_files) И «ФОН» В (ВЫБЕРИТЕ источник ИЗ group_postprocessing_files) ) -- CD. Вставьте эти новые задания и подключите файлы -- Должен зацикливаться только один раз ДЛЯ loop_uurid IN ВЫБЕРИТЕ ОТЛИЧНЫЕ uurid ОТ job_candidate ПЕТЛЯ -- в.
Вставить задания С работой КАК ( -- TODO Поддержка not_before и приоритета ВЫБЕРИТЕ enqueue_job AS uujid ОТ enqueue_job (uurid, '', 'ПОСТОБРАБОТКА') ) -- д. Подключить новые задания к файлам ВСТАВИТЬ В files_to_jobs ВЫБЕРИТЕ job_candidate.uufid, job.uujid С работы; КОНЕЦ ПЕТЛИ; КОНЕЦ ПЕТЛИ; КОНЕЦ $$;

Итак, мои вопросы:

  1. Как использовать цикл FOR в сочетании с выбором WITH?
  2. Если это невозможно, как иначе получить данные временной таблицы, которые я могу перебрать в цикле?
  • postgresql
  • plpgsql

Вы можете использовать цикл FOR в сочетании с предложением WITH, но предложение WITH должно принадлежать оператору SELECT (предложение WITH не является независимым оператором):

 DO
$$
ОБЪЯВИТЬ loop_col1 RECORD;
НАЧИНАТЬ
    FOR loop_col1 IN
        С temp_table КАК (
         ВЫБЕРИТЕ col1, col2 ИЗ файлов
        )
        ВЫБЕРИТЕ ОТЛИЧНЫЙ col1 ОТ temp_table
    ПЕТЛЯ
        -- сделай что-нибудь
        поднять уведомление 'loop_uurid %', loop_col1;
    КОНЕЦ ПЕТЛИ;
КОНЕЦ $$;
 

В противном случае вы можете создать временную таблицу:

 DO $$
ОБЪЯВИТЬ loop_col1 RECORD;
НАЧИНАТЬ
    СОЗДАТЬ ВРЕМЕННУЮ ТАБЛИЦУ temp_table ON COMMIT DROP AS
        ВЫБРАТЬ col1, col2 ИЗ файлов;
    FOR loop_col1 IN
        ВЫБЕРИТЕ ОТЛИЧНЫЙ col1 ОТ temp_table
    ПЕТЛЯ
        -- сделай что-нибудь
        поднять уведомление 'loop_uurid %', loop_col1;
    КОНЕЦ ПЕТЛИ;
КОНЕЦ $$;
 

5

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя электронную почту и пароль

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

postgresql — Генерация запросов просмотра с использованием цикла

У меня есть этот запрос PostgreSQL, где у меня есть 2x $i в нотации, похожей на bash, чтобы было понятно, что я хочу распечатать число i в диапазоне от 0 до 20 в этих позициях с помощью цикла for. prefix%’ И table_name НЕ КАК ‘%suffix$’ И table_schema не в (‘information_schema’, ‘pg_catalog’) И table_type = ‘БАЗОВАЯ ТАБЛИЦА’ ORDER BY имя_таблицы;

Обратите также внимание, что этот оператор SELECT уже зацикливается на N таблицах.

Из того, что я прочитал до сих пор, это будет структура, в которую можно встроить мой код:

 DO $$
НАЧИНАТЬ
    FOR i IN 0..20 ЦИКЛ
        -- вставьте сюда предыдущий запрос
    RAISE NOTICE 'номер фактора: %', i;
    КОНЕЦ ПЕТЛИ;
КОНЕЦ; $$
 

Но когда я делаю это и фактически выполняю его, я получаю это сообщение об ошибке:

 ОШИБКА: запрос не имеет назначения для данных результатов
СОВЕТ: Если вы хотите отказаться от результатов SELECT, вместо этого используйте PERFORM.
КОНТЕКСТ: функция PL/pgSQL inline_code_block, строка 4 в операторе SQL
Состояние SQL: 42601
 

И если я заменю SELECT на PERFORM , в моем файле останется одно слово «DO».

Как я могу генерировать все свои запросы, используя цикл for?

Результирующие запросы должны выглядеть так:

 СОЗДАТЬ МАТЕРИАЛИЗОВАННОЕ ПРЕДСТАВЛЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ "prefix1_table_0" AS SELECT id, 1 AS factor FROM "prefix_table" WHERE factor NOT NULL;
СОЗДАЙТЕ МАТЕРИАЛИЗОВАННОЕ ПРЕДСТАВЛЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ "prefix1_table_1", КАК ВЫБРАТЬ id, 2 КАК фактор ИЗ "prefix_table", ГДЕ фактор НЕ НУЛЬ;
.
.. СОЗДАЙТЕ МАТЕРИАЛИЗОВАННОЕ ПРЕДСТАВЛЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ «prefix1_table_20», КАК ВЫБРАТЬ id, 1048576 КАК фактор ИЗ «prefix_table», ГДЕ фактор НЕ НУЛЬ; ... СОЗДАЙТЕ МАТЕРИАЛИЗОВАННОЕ ПРЕДСТАВЛЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ "prefixN_table_0", КАК ВЫБРАТЬ id, 1 КАК фактор ИЗ "prefix_table", ГДЕ фактор НЕ НУЛЬ; СОЗДАЙТЕ МАТЕРИАЛИЗОВАННОЕ ПРЕДСТАВЛЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ "prefixN_table_1", КАК ВЫБЕРИТЕ id, 2 КАК фактор ИЗ "prefix_table", ГДЕ фактор НЕ НУЛЬ; ... СОЗДАЙТЕ МАТЕРИАЛИЗОВАННОЕ ПРЕДСТАВЛЕНИЕ, ЕСЛИ НЕ СУЩЕСТВУЕТ "prefixN_table_20", КАК ВЫБРАТЬ id, 1048576 КАК фактор ИЗ "prefix_table", ГДЕ фактор НЕ НУЛЬ;

Точность: я сохраняю этот оператор SQL в файле /sql_queries/generate_views_queries.sql и выполняю его для вывода результирующих запросов в другой файл /sql_queries/do_create_views.sql :

 psql -d "host=$ Порт {HOST}=${PORT} dbname=${POSTGRES_DB} пользователь=${POSTGRES_USER} пароль=${POSTGRES_PASSWORD}" \
 -f "/sql_queries/generate_views_queries.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *