Удаление 'union all' в конце последней записи в динамическом запросе - PullRequest
0 голосов
/ 14 ноября 2018

Для моего вопроса я создал простой пример, иллюстрирующий мою проблему.

Допустим, у вас есть динамический запрос, который генерирует несколько операторов выбора с UNION ALL между ними. Есть ли способ предотвратить появление 'UNION ALL' в конце последней записи?

Мой пример:

CREATE OR REPLACE PROCEDURE PROC_TEST AS 
BEGIN
    DECLARE 
        DDL_STRING CLOB;
    BEGIN
        FOR x IN (SELECT TABLE_NAME FROM HLP_TABLES WHERE ENABLED = 1)
        LOOP
            DDL_STRING := 'SELECT ID FROM ' || x.TABLE_NAME || ' UNION ALL ';
            DBMS_OUTPUT.PUT_LINE(DDL_STRING);
        END LOOP;
    END;
END PROC_TEST;

Ответы [ 4 ]

0 голосов
/ 27 ноября 2018

При генерации кода, подобного этому, я обычно использую простое утверждение if, например ::

create or replace procedure proc_test as 
  ddl_string clob;
begin

  for x in (select table_name from hlp_tables where enabled = 1)
  loop

    if ddl_string is not null then
      ddl_string := ddl_string || ' union all ';
    end if;

    ddl_string := ddl_string || ' select id from ' || x.table_name;

  end loop;

  dbms_output.put_line(ddl_string);
end proc_test;
0 голосов
/ 14 ноября 2018

Если вы уверены, что общая длина ddl не превышает 4000 символов, вы можете использовать LISTAGG и избегать циклов.

CREATE OR REPLACE PROCEDURE proc_test
     AS
     DECLARE
          ddl_string   CLOB;
     BEGIN
          SELECT
               LISTAGG('SELECT ID FROM ' || table_name,' UNION ALL ') WITHIN GROUP(
                    ORDER BY table_name)
          INTO ddl_string 
          FROM HLP_TABLES
     WHERE enabled = 1;
          dbms_output.put_line(ddl_string);
END proc_test;
/
0 голосов
/ 14 ноября 2018

Вы можете использовать счетчик в цикле, чтобы определить, нужен ли вам UNION ALL или нет. попробуйте это:

  CREATE OR REPLACE PROCEDURE PROC_TEST AS
  BEGIN
    DECLARE
      v_counter  number := 1;
      DDL_STRING CLOB;
    BEGIN
      FOR x IN (SELECT TABLE_NAME FROM HLP_TABLES WHERE ENABLED = 1) LOOP

        DDL_STRING := case
                        when v_counter > 1 then
                         ' UNION ALL ' end || ' SELECT ID FROM ' || x.TABLE_NAME;
        DBMS_OUTPUT.PUT_LINE(DDL_STRING);
        v_counter := v_counter + 1;
      END LOOP;
    END;
  END PROC_TEST;
0 голосов
/ 14 ноября 2018

Сделайте это:

CREATE OR REPLACE PROCEDURE PROC_TEST AS 
   DDL_STRING CLOB;
BEGIN
    FOR x IN (SELECT TABLE_NAME FROM HLP_TABLES WHERE ENABLED = 1)
    LOOP
        DDL_STRING := DDL_STRING||' SELECT ID FROM ' || x.TABLE_NAME || ' UNION ALL';
    END LOOP;
    DDL_STRING := REGEXP_REPLACE(DDL_STRING, ' UNION ALL$');
    DBMS_OUTPUT.PUT_LINE(DDL_STRING);
END PROC_TEST;
...