2017-01-29 8 views
1

Я пытаюсь выполнить операцию над своей процедурой, но это не работает для меня. Я хочу показать имя файла рядом с таблицами, которые у него есть, но не повторяя имени файла, я объясню лучше. Скажем, у меня есть эта таблица:Застрял в моей процедуре [ORACLE]

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

Надеюсь, я хорошо объяснил и поблагодарил вас за помощь.

+0

* Никогда * Используйте запятые в 'п от'. * Всегда * используйте правильный, явный синтаксис JOIN. –

+0

@ GordonLinoff Большое спасибо за совет. – Randomuser1204281

+0

@ Randomuser1204281 Вам также нужно заказать по файлу. – BobC

ответ

0

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

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

Проблема в том, что вы вводите файл, даже если он повторяется. Если вы изменили код, как описано ниже, вы достигнете решение легко:

  1. Создать переменную для имени файла и инициализировать его с пустой varchar перед циклом

  2. Вместо того, чтобы вводить имя файла, который вы следует проверить, имеет ли переменная то же значение, что и имя файла. Если нет, то введите файл, в противном случае не вводите его

  3. После обработал имя файла и напечатал, если он был новый, хранится имя файла в переменной

0

Если вы используете свой отчет в 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 
; 
3

Вы можете достигнуть своей цели только чистым 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