卡在我的程序中 [ORACLE]
Stuck in my procedure [ORACLE]
我正在尝试对我的程序执行操作,但它对我不起作用。我想在 table 旁边显示文件名,但不重复文件名,我解释得更好。假设我有这个 table:
-----------------------------------
| file | name_table|
| ----------------------------------|
| /home/peter/f1.dbf | table1.1 |
| /home/peter/f1.dbf | table1.2 |
| /home/peter/f2.dbf | table2.1 |
| /home/peter/f3.dbf | table3.1 |
| /home/peter/f3.dbf | table3.2 |
-----------------------------------
当我 运行 我的程序时,它应该显示如下内容:
File: f1.dbf
Table1.1
Table1.2
File: f2.dbf
Table2.1
File: f3.dbf
Table3.1
Table3.2
我试过以下程序:
create or replace procedure files(p_user IN dba_segments.owner%type)
is
cursor c_cursor is
select d.file_name, s.segment_name, s.segment_type
from dba_data_files d, dba_segments s
where segment_type = 'TABLE'
and s.owner=p_user;
v_cursor c_cursor%rowtype;
begin
for v_cursor in c_cursor loop
if v_cursor.segment_type='TABLE' then
dbms_output.put_line('File' || v_cursor.file_name);
dbms_output.put_line(' Table Nº:'' '|| v_cursor.segment_name);
end if;
end loop;
end files;
/
但是我的程序结果如下:
File: /home/peter/f1.dbf
Table1.1
File: /home/peter/f1.dbf
Table1.2
File: /home/peter/f2.dbf
Table2.1
File: /home/peter/f3.dbf
Table3.1
File: /home/peter/f3.dbf
Table3.2
希望我解释得很好,谢谢你的帮助。
问题是你输入了文件,即使它是重复的。如果您按如下所述修改代码,您将很容易找到解决方案:
为文件名创建一个变量并在循环之前用空varchar
初始化它
您应该检查变量是否与文件名具有相同的值,而不是键入文件名。如果没有,则键入该文件,否则不键入它
处理文件名并输入新文件名后,将文件名存储在变量中
如果您运行您的报表在 SQLPlus 中,那么您可以简单地使用 BREAK 命令
break on file_name
select d.file_name, s.segment_name, s.segment_type
from dba_data_files d, dba_segments s
where segment_type = 'TABLE'
and s.owner=&p_user
order by d.file_name
;
只有纯粹的sql才能实现你的目标。
select s_file, s_name
from ( select d.file_name
, s.segment_name as s_name
, row_number() over(partition by file_name order by 1) rn
, case when grouping_id(segment_name) = 1 then 'File: ' || d.file_name end s_file
from dba_data_files d, dba_segments s
where segment_type = 'TABLE' and s.owner = user
group by file_name, rollup(segment_name))
order by file_name, rn desc
您可以使用两个光标而不是一个:
CREATE OR REPLACE PROCEDURE FILES (P_USER IN DBA_SEGMENTS.OWNER%TYPE)
IS
CURSOR C_FILE
IS
SELECT D.FILE_NAME
FROM DBA_DATA_FILES D, DBA_SEGMENTS S
WHERE SEGMENT_TYPE = 'TABLE' AND S.OWNER = P_USER
GROUP BY D.FILE_NAME;
CURSOR C_SEGMENT (
P_FILE IN VARCHAR2)
IS
SELECT SEGMENT_NAME
FROM DBA_DATA_FILES D, DBA_SEGMENTS S
WHERE SEGMENT_TYPE = 'TABLE'
AND S.OWNER = P_USER
AND D.FILE_NAME = P_FILE;
BEGIN
FOR REC_FILE IN C_FILE
LOOP
DBMS_OUTPUT.PUT_LINE ('File' || REC_FILE.FILE_NAME);
FOR REC_SEG IN C_SEGMENT (REC_FILE.FILE_NAME)
LOOP
DBMS_OUTPUT.PUT_LINE (' Table Nº:'' ' || REC_SEG.SEGMENT_NAME);
END LOOP;
END LOOP;
END FILES;
我正在尝试对我的程序执行操作,但它对我不起作用。我想在 table 旁边显示文件名,但不重复文件名,我解释得更好。假设我有这个 table:
-----------------------------------
| file | name_table|
| ----------------------------------|
| /home/peter/f1.dbf | table1.1 |
| /home/peter/f1.dbf | table1.2 |
| /home/peter/f2.dbf | table2.1 |
| /home/peter/f3.dbf | table3.1 |
| /home/peter/f3.dbf | table3.2 |
-----------------------------------
当我 运行 我的程序时,它应该显示如下内容:
File: f1.dbf
Table1.1
Table1.2
File: f2.dbf
Table2.1
File: f3.dbf
Table3.1
Table3.2
我试过以下程序:
create or replace procedure files(p_user IN dba_segments.owner%type)
is
cursor c_cursor is
select d.file_name, s.segment_name, s.segment_type
from dba_data_files d, dba_segments s
where segment_type = 'TABLE'
and s.owner=p_user;
v_cursor c_cursor%rowtype;
begin
for v_cursor in c_cursor loop
if v_cursor.segment_type='TABLE' then
dbms_output.put_line('File' || v_cursor.file_name);
dbms_output.put_line(' Table Nº:'' '|| v_cursor.segment_name);
end if;
end loop;
end files;
/
但是我的程序结果如下:
File: /home/peter/f1.dbf
Table1.1
File: /home/peter/f1.dbf
Table1.2
File: /home/peter/f2.dbf
Table2.1
File: /home/peter/f3.dbf
Table3.1
File: /home/peter/f3.dbf
Table3.2
希望我解释得很好,谢谢你的帮助。
问题是你输入了文件,即使它是重复的。如果您按如下所述修改代码,您将很容易找到解决方案:
为文件名创建一个变量并在循环之前用空
varchar
初始化它您应该检查变量是否与文件名具有相同的值,而不是键入文件名。如果没有,则键入该文件,否则不键入它
处理文件名并输入新文件名后,将文件名存储在变量中
如果您运行您的报表在 SQLPlus 中,那么您可以简单地使用 BREAK 命令
break on file_name
select d.file_name, s.segment_name, s.segment_type
from dba_data_files d, dba_segments s
where segment_type = 'TABLE'
and s.owner=&p_user
order by d.file_name
;
只有纯粹的sql才能实现你的目标。
select s_file, s_name
from ( select d.file_name
, s.segment_name as s_name
, row_number() over(partition by file_name order by 1) rn
, case when grouping_id(segment_name) = 1 then 'File: ' || d.file_name end s_file
from dba_data_files d, dba_segments s
where segment_type = 'TABLE' and s.owner = user
group by file_name, rollup(segment_name))
order by file_name, rn desc
您可以使用两个光标而不是一个:
CREATE OR REPLACE PROCEDURE FILES (P_USER IN DBA_SEGMENTS.OWNER%TYPE)
IS
CURSOR C_FILE
IS
SELECT D.FILE_NAME
FROM DBA_DATA_FILES D, DBA_SEGMENTS S
WHERE SEGMENT_TYPE = 'TABLE' AND S.OWNER = P_USER
GROUP BY D.FILE_NAME;
CURSOR C_SEGMENT (
P_FILE IN VARCHAR2)
IS
SELECT SEGMENT_NAME
FROM DBA_DATA_FILES D, DBA_SEGMENTS S
WHERE SEGMENT_TYPE = 'TABLE'
AND S.OWNER = P_USER
AND D.FILE_NAME = P_FILE;
BEGIN
FOR REC_FILE IN C_FILE
LOOP
DBMS_OUTPUT.PUT_LINE ('File' || REC_FILE.FILE_NAME);
FOR REC_SEG IN C_SEGMENT (REC_FILE.FILE_NAME)
LOOP
DBMS_OUTPUT.PUT_LINE (' Table Nº:'' ' || REC_SEG.SEGMENT_NAME);
END LOOP;
END LOOP;
END FILES;