尝试将输出写入目录中的 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);
我正在尝试将一些监控信息输出到 .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);