Создайте операторы UNION ALL через цикл - PullRequest
0 голосов
/ 12 марта 2019

Вручную, я могу выбрать разделы во внутреннем запросе с первым блоком кода ниже. Есть ли способ сделать это более элегантным способом через цикл? Здесь я показываю 3 раздела, но у меня их около 200, и разделы основаны на столбце даты, и поэтому имена разделов необходимо будет изменить, когда я снова выполню этот запрос в будущем.

SELECT *
FROM ( 

        SELECT * FROM RSS_ACQ.TRX_ARQ PARTITION("SYS_P211048") UNION ALL 
        SELECT * FROM RSS_ACQ.TRX_ARQ PARTITION("SYS_P210329") UNION ALL
        SELECT * FROM RSS_ACQ.TRX_ARQ PARTITION("SYS_P176323")

     )  TRX_ARQ
;

С помощью этого оператора я создал цикл, который выводит операторы UNION ALL.

BEGIN
  FOR ALL_TAB_PARTITIONS IN 
      ( 
              SELECT PARTITION_NAME
              FROM ALL_TAB_PARTITIONS
              where TABLE_OWNER = 'TABLEOWNER'
              AND TABLE_NAME = 'TABLENAME'
              AND PARTITION_POSITION > 123
              ORDER BY partition_position DESC 
        )      
            LOOP
   DBMS_OUTPUT.PUT_LINE( 'SELECT * FROM RSS_ACQ.TRX_ARQ PARTITION(\"' 
                                             || ALL_TAB_PARTITIONS.PARTITION_NAME || '\") UNION ALL');
  END LOOP;
END;

И в этом блоке я попытался использовать цикл внутри внутреннего запроса. Он еще не отформатирован правильно, и мне нужно избегать UNION ALL для самого последнего раздела.

SELECT *
FROM ( 
            BEGIN
            FOR ALL_TAB_PARTITIONS IN 
                  ( 
                          SELECT PARTITION_NAME
                          FROM ALL_TAB_PARTITIONS
                          where TABLE_OWNER = 'TABLEOWNER'
                          AND TABLE_NAME = 'TABLENAME'
                          AND PARTITION_POSITION > 123
                          ORDER BY partition_position DESC 
                    )      
                        LOOP
               DBMS_OUTPUT.PUT_LINE( 'SELECT * FROM RSS_ACQ.TRX_ARQ PARTITION(\"' 
      || ALL_TAB_PARTITIONS.PARTITION_NAME || '\") UNION ALL');
              END LOOP;
            END;      
     )  TRX_ARQ
;

Вот некоторые из ошибок, но было и много других. Это синтаксические ошибки, указывающие на другие части запроса, поэтому я ожидаю, что у меня возникнет проблема с выходом из кавычек.

Error starting at line : 99 in command -
END LOOP
Error report -
Unknown Command

Error starting at line : 100 in command -
END
Error report -
Unknown Command

Error starting at line : 101 in command -
)
Error report -
Unknown Command

Error starting at line : 102 in command -
)  TABLENAME
Error report -
Unknown Command

Ответы [ 2 ]

2 голосов
/ 12 марта 2019

Это немного догадка, но это слишком долго для комментария.

Я предполагаю, что ваша таблица разбита на интервалы.В этом случае получение всех данных с позиций раздела> 123 - это то же самое, что получение всех строк с более высокой датой, чем самая высокая дата в разделе 123.

Вы можете получить эту дату из ALL_TAB_PARTITIONS, а затемиспользуйте его для запроса таблицы.Как это:

WITH FUNCTION get_high_value RETURN DATE IS 
  l_high_val_expr ALL_TAB_PARTITIONS.HIGH_VALUE%TYPE;
  l_high_value DATE;
BEGIN
  SELECT high_value
  INTO   l_high_val_expr
  FROM   all_tab_partitions 
  WHERE  table_owner = 'RSS_ACQ'
  AND    table_Name = 'TRX_ARQ'
  and    partition_position = 123; 

  EXECUTE IMMEDIATE 'SELECT ' || l_high_val_expr || ' FROM DUAL' INTO l_high_value;

  RETURN l_high_value;
END;
SELECT * FROM rss_acq.trx_arq
-- Replace "partitioned_date_column" with the name of the column on which the
-- table is interval partitioned.
WHERE partitioned_date_column > get_high_value;
2 голосов
/ 12 марта 2019

Мы не можем выполнить анонимный блок PL / SQL в операторе SELECT.

Что вам нужно сделать, это перенести выходные данные цикла ALL_TAB_PARTITIONS в файл (или рабочую таблицу SQL, если вы используете IDE, например, SQL Developer). Это даст вам скрипт, который вы можете запустить отдельно после его редактирования (вам нужно обрезать UNION ALL из окончательного сгенерированного SELECT.

Возможно, есть более изящные способы достижения того же самого, но задача кажется достаточно неправильной, так что она не кажется мне стоящей. Вы хотите запросить 200 разделов в одном операторе. Это операция грубой силы, и нельзя запрашивать именованные блоки. На самом деле создание объединения из 200 отдельных запросов может оказаться более дорогостоящим, чем один запрос. Так почему бы не попробовать что-то подобное?

select * from RSS_ACQ.TRX_ARQ
where partition_key_col >= date '2018-08-01' -- or whatever    

«Я думаю, что вы пропускаете возможность 12c использования PL / SQL в предложении WITH»

Эта функция 12c предназначена для функций , а не процедур, поэтому она не поможет оператору выполнить их код. Можно было бы использовать функцию предложения WITH, но для этого потребовалось бы:

  • создание типа с той же проекцией, что и у целевой таблицы
  • и вложенный тип таблицы на основе этого типа
  • функция предложения WITH, которая собирает и выполняет динамический оператор SQL
  • мы не можем использовать REF CURSOR в SQL, так что ...
  • функция должна выполнить динамический выбор INTO локальной переменной коллекции ...
  • затем переберите коллекцию и PIPE ROW, чтобы вывести эти строки ...
  • , поэтому основной запрос может вызвать функцию с помощью table() call

Может ли функция предложения WITH быть конвейерной? Я не могу найти ничего в документации, чтобы сказать, что мы не можем (сейчас у меня нет доступа к 12c для тестирования).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...