Попытка записать вывод в CSV в каталог, сбой с PLS-00302 - PullRequest
0 голосов
/ 23 января 2019

Я пытаюсь вывести некоторую информацию о мониторинге в файл .csv.Я должен придерживаться "Basic" рамки кода.Проблема заключается в том, чтобы заставить его выводить в .csv / получать код для компиляции.

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

create or replace procedure WRITE_EST_SIZE_01 is
  file_handle UTL_FILE.file_type;
begin
  file_handle := utl_file.fopen('ESTIMATES_CSV', 
                                'csv_filename' || 
                                   to_char(sysdate,'MONYYYY')||'.csv',
                                'w', 32767);
  for rws in (SELECT 'OWNER' || ',' || 
                     'SEGMENT_NAME' || ',' ||
                     'U' || ',' ||
                     'SUM_BYTES'
                FROM
              union ALL
              select /*+ parallel*/
                     s.owner || ',' ||
                     s.segment_name || ',' ||
                     'U' || ',' ||
                     sum(s.bytes)/1024/1024 
                from DBA_SEGMENTS s
                where s.owner = (select distinct targetschema
                                   from pdu.pdu_table) and
                      s.segment_name in (select table_name
                                           from another_table) and 
                      s.segment_type LIKE '%TABLE%'
                group by s.owner, s.segment_name
              union all
              select /*+ parallel*/
                     i.table_owner || ',' || 
                     i.table_name || ',' ||
                     'I' || ',' ||
                     sum(s.bytes)/1024/1024
                from DBA_SEGMENTS s,
                     DBA_INDEXES  i
                where i.table_owner  = (select distinct targetschema
                                          from pdu.pdu_table) and
                      i.table_name in (select table_name
                                         from another_table) and
                      i.owner = s.owner and
                      i.index_name = s.segment_name and
                      s.segment_type like '%INDEX%'
                group by i.table_owner, i.table_name
              union all
              select /*+ parallel*/
                     l.owner || ',' ||
                     l.table_name || ',' ||
                     'L' || ',' ||
                     sum(s.bytes)/1024/1024
                from DBA_SEGMENTS s,
                     ALL_LOBS l
                where l.owner = (select distinct targetschema
                                   from another_table) and
                      l.table_name in (select table_name
                                         from another_table) and
                      l.owner = s.owner and
                      l.segment_name = s.segment_name
                group by l.owner, l.table_name
                --order by 1, 2)
  loop
    utl_file.put_line(file_handle,
                      rws.OWNER || ',' ||
                      rws.SEGMENT_NAME || ',' ||
                      rws.U || ',' ||
                      rws.SUM_BYTES -- your columns here
                      );
  end loop;

  utl_file.fclose(file_handle);
end WRITE_EST_SIZE_01;

Это на самом деле не компилируется, но жалуетсячто rws.OWNER должен быть объявлен.Он компилируется, если я поставлю все rws.в кавычках, но затем вывод csv перезаписывается тем, что находится в кавычках.Может кто-нибудь увидеть способ сделать это, когда он на самом деле "будет" сбросить вывод SQL в CSV?

Ответы [ 3 ]

0 голосов
/ 23 января 2019

В вашем SQL вы создаете объединенную строку, когда кажется, что вы просто хотите получить отдельные поля. Я предлагаю:

create or replace procedure WRITE_EST_SIZE_01 is
  file_handle UTL_FILE.file_type;
begin
  file_handle := utl_file.fopen('ESTIMATES_CSV', 
                                'csv_filename' || 
                                   to_char(sysdate,'MONYYYY')||'.csv',
                                'w', 32767);
  for rws in (select s.owner,
                     s.segment_name,
                     'U' AS FLAG,
                     sum(s.bytes)/1024/1024 AS SUM_BYTES
                from DBA_SEGMENTS s
                where s.owner = (select distinct targetschema
                                   from pdu.pdu_table) and
                      s.segment_name in (select table_name
                                           from another_table) and 
                      s.segment_type LIKE '%TABLE%'
                group by s.owner, s.segment_name
              union all
              select i.table_owner AS OWNER,
                     i.table_name AS SEGMENT_NAME,
                     'I' AS FLAG,
                     sum(s.bytes)/1024/1024 AS SUM_BYTES
                from DBA_SEGMENTS s,
                     DBA_INDEXES  i
                where i.table_owner  = (select distinct targetschema
                                          from pdu.pdu_table) and
                      i.table_name in (select table_name
                                         from another_table) and
                      i.owner = s.owner and
                      i.index_name = s.segment_name and
                      s.segment_type like '%INDEX%'
                group by i.table_owner, i.table_name
              union all
              select l.owner,
                     l.table_name AS SEGMENT_NAME,
                     'L' AS FLAG,
                     sum(s.bytes)/1024/1024 AS SUM_BYTES
                from DBA_SEGMENTS s,
                     ALL_LOBS l
                where l.owner = (select distinct targetschema
                                   from another_table) and
                      l.table_name in (select table_name
                                         from another_table) and
                      l.owner = s.owner and
                      l.segment_name = s.segment_name
                group by l.owner, l.table_name
                --order by 1, 2)
  loop
    utl_file.put_line(file_handle,
                      rws.OWNER || ',' ||
                      rws.SEGMENT_NAME || ',' ||
                      rws.FLAG || ',' ||
                      rws.SUM_BYTES -- your columns here
                      );
  end loop;

  utl_file.fclose(file_handle);
end WRITE_EST_SIZE_01;
0 голосов
/ 23 января 2019

Когда вы пишете:

   ) loop
utl_file.put_line(file_handle, rws.OWNER||','||rws.SEGMENT_NAME||','||rws.U||','||rws.SUM_BYTES);

, вы используете имена столбцов, которые должны быть описаны в запросе внутри for rws in (select ...) loop.В настоящее время этот оператор SELECT имеет только один столбец с автоматически генерируемым именем.Вам нужно изменить его на:

SELECT 'OWNER' owner, 'SEGMENT_NAME' segment_name, 'U' u, 'SUM_BYTES' sum_bytes
  FROM dual
 union all
select /*+ parallel*/
       s.owner, s.segment_name, 'U', sum(s.bytes)/1024/1024 
  from ...

Кроме того, вам нужно изменить все остальные подзапросы таким образом.

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

for rws in (SELECT 'OWNER,SEGMENT_NAME,U,SUM_BYTES' row_data
                FROM
              union ALL

И изменить последнюю строку:

...
) loop
utl_file.put_line(file_handle, rws._row_data);
0 голосов
/ 23 января 2019

Ваш запрос курсора выполняет конкатенацию в каждой ветви объединения, поэтому, если вы запустите эту автономную программу, вы увидите набор результатов с одним столбцом. Когда вы пытаетесь обработать цикл, вы пытаетесь найти отдельного владельца / сегмент / и т.д. - но они не являются частью проекции из этого запроса курсора.

Если вы задаете псевдоним для единственного сгенерированного столбца, по крайней мере, в первой ветви:

SELECT 'OWNER'||','||'SEGMENT_NAME'||','||'U'||','||'SUM_BYTES' AS CSV_TEXT

или более просто:

SELECT 'OWNER,SEGMENT_NAME,U,SUM_BYTES' AS CSV_TEXT

тогда в вашем цикле вы можете сослаться на этот псевдоним:

utl_file.put_line(file_handle, rws.CSV_TEXT);

Хотя, вероятно, было бы проще просто записать строку заголовка в файл непосредственно перед циклом курсора, вместо того, чтобы сделать его частью этого запроса:

utl_file.put_line(file_handle, 'OWNER,SEGMENT_NAME,U,SUM_BYTES');

Затем вы можете сохранить объединение в оставшихся ветвях объединения с одним и тем же псевдонимом значения столбца; или пусть ветви объединения получают необработанные столбцы (владелец и т. д.) без объединения, а затем сохраняют объединение внутри цикла. [Поскольку ответ @BobJarvis 'делает!] Но не делайте обоих ...

...