尝试将输出写入目录中的 CSV,失败并显示 PLS-00302

Trying to write output to a CSV on a directory, failing with PLS-00302

我正在尝试将一些监控信息输出到 .csv 文件中。我必须坚持代码的 "Basic" 框架。问题是让它输出到 .csv/getting 要编译的代码。

我已经尝试过各种方法,但现在我卡住了,我发现自己经常移动引号和双引号。

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 输出被引号中的内容覆盖。谁能看到这样做的方法,它实际上 "Will" 将 sql 的输出转储到 .csv?

您的游标查询在并集的每个 b运行ch 中进行串联,因此如果您 运行 独立查询,您会看到只有一个列的结果集。当您尝试处理循环时,您正在尝试寻找个体 owner/segment/etc。 - 但它们不是该游标查询的投影的一部分。

如果您给单个生成的列值一个别名,至少在第一个 b运行ch:

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);

尽管直接在游标循环之前将 header 行写入文件可能更简单,而不是将其作为该查询的一部分:

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

然后您可以在剩余的并集 b运行ches 中使用相同的单个 column-value 别名保持串联;或者让联合 b运行ches 在不连接的情况下获取原始列(所有者等),然后将连接保持在循环内。 [正如@BobJarvis 的回答所做的那样!] 但不要两者都做...

在您的 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;

当你写:

   ) 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);