2016-09-07 8 views
0

employeesの従業員名をフラット・ファイルにエクスポートしようとしています。フラット・ファイルには、次のような構造を持っている必要があります。UTL_FILEを使用してループ内のフラット・ファイルにデータを書き込む

HEADER 
DETAILS JACK 
DETAILS JUNE 
TRAILER 

私は何に苦しんでいますが、私は同じファイル内の単一の行の名前を格納するためのループでこれを実行する方法にあります。現在のスクリプトでは、一度に1つの名前を別々のファイルにエクスポートしています。ファイル名は同じなので、プロシージャが実行されるたびにファイルが上書きされます。

可能であれば、ファイル名を変数として使用したいと考えています。

Create table Employees (Id number(10),Name varchar(40)) 

Insert into Employees values (1,'JOHN'); 
Insert into Employees values (2,'JACK'); 
Insert into Employees values (3,'JUNE'); 
----------------------- 

CREATE OR REPLACE Procedure PRINT_NAMES(aId  in Employees.Id%Type, 
             aFileName in varchar2) 

Is 

    fDirectory varchar(30) := 'SB1KK_TEMP'; 
    fName  Employees.name%Type; 

    pFile Utl_File.file_type; 
    fLine Varchar2(1024); 

Begin 



    pFile := UTL_FILE.fopen(fDirectory, aFileName, 'w'); 

    --File Header 
    fLine := RPAD('HEADER', 10) || To_char(trunc(sysdate), 'yyyymmdd') || '000000'; 
    UTL_FILE.put_line(pFile, convert(fLine, 'WE8ISO8859P1', 'UTF8')); 

    --File Details - This Section must be run in a loop 
    Select Name into fName From Employees where id = aId; 
    fLine := RPAD('DETAILS', 10) || RPAD(' ', 50) || 
      To_char(trunc(sysdate), 'yyyymmdd') || RPAD(fName, 11); 
    UTL_FILE.put_line(pFile, convert(fLine, 'WE8ISO8859P1', 'UTF8')); 


    --File Trailer 
    fLine := RPAD('TRAILER', 10) || To_char(trunc(sysdate), 'yyyymmdd') || '000000'; 
    UTL_FILE.put_line(pFile, convert(fLine, 'WE8ISO8859P1', 'UTF8')); 
    UTL_FILE.fclose(pFile); 

End; 
/

ストアドプロシージャはループ内で実行されます。ファイルTMP_LOG.txtはテーブルemployeesの各人物に繰り返し作成されます。

Begin 
    For IDS in (Select * From Employees Where id in (2,3)) 
    Loop 
    PRINT_NAMES(aId => IDS.ID, aFileName => 'TMP_LOG.TXT'); 
    End Loop; 
End; 

答えて

1

プロシージャを呼び出すときはありませんあなたのコード内のコメントがすでに示唆するように、あなたのプロシージャ内でループを実行する必要があり、そして。しかし、それはあなたが複数のIDを渡す必要があるということを行うための簡単な方法を、あなたが新しいユーザー定義型を作成するために許可されている場合、テーブルのコレクションである:。

CREATE Type EmployeeIds as Table of Number(10) 
/

その後、あなたのプロシージャの宣言は次のようになります。

CREATE OR REPLACE Procedure PRINT_NAMES(aIds  in EmployeeIds, 
             aFileName in varchar2) 

とカーソルループ行うことができます。

For IDS in (Select * From Employees Where ID member of aIds) Loop 
    fLine := RPAD('DETAILS', 10) || RPAD(' ', 50) || 
      To_char(trunc(sysdate), 'yyyymmdd') || RPAD(IDS.Name, 11); 
    UTL_FILE.put_line(pFile, convert(fLine, 'WE8ISO8859P1', 'UTF8')); 
    End Loop; 

をあなたはfnameローカル変数を必要としません。

だから、完全に次のようになります。

CREATE OR REPLACE Procedure PRINT_NAMES(aIds  in EmployeeIds, 
             aFileName in varchar2) 

Is 

    fDirectory varchar(30) := 'SB1KK_TEMP'; 

    pFile Utl_File.file_type; 
    fLine Varchar2(1024); 

Begin 



    pFile := UTL_FILE.fopen(fDirectory, aFileName, 'w'); 

    --File Header 
    fLine := RPAD('HEADER', 10) || To_char(trunc(sysdate), 'yyyymmdd') || '000000'; 
    UTL_FILE.put_line(pFile, convert(fLine, 'WE8ISO8859P1', 'UTF8')); 

    --File Details - This Section must be run in a loop 
    For IDS in (Select * From Employees Where ID member of aIds) Loop 
    fLine := RPAD('DETAILS', 10) || RPAD(' ', 50) || 
      To_char(trunc(sysdate), 'yyyymmdd') || RPAD(IDS.Name, 11); 
    UTL_FILE.put_line(pFile, convert(fLine, 'WE8ISO8859P1', 'UTF8')); 
    End Loop; 

    --File Trailer 
    fLine := RPAD('TRAILER', 10) || To_char(trunc(sysdate), 'yyyymmdd') || '000000'; 
    UTL_FILE.put_line(pFile, convert(fLine, 'WE8ISO8859P1', 'UTF8')); 
    UTL_FILE.fclose(pFile); 

End; 
/

そして、あなたは同じUDTを使用して、IDのコレクションでそれを呼び出す:

Begin 
    PRINT_NAMES(aIds => EmployeeIds(2,3), aFileName => 'TMP_LOG.TXT'); 
End; 
/

では、含まれているファイルを生成します。

HEADER 20160907000000 
DETAILS              20160907JACK 
DETAILS              20160907JUNE 
TRAILER 20160907000000 

あなたが移入して代わりにプロシージャに渡すコレクション変数を持つことができます。例:

Declare 
    lIds EmployeeIds; 
Begin 
    -- populate the collection from the table using criteria you need 
    Select ID Bulk Collect Into lIds From EmployeesX Where ID in (2,3); 
    PRINT_NAMES(aIds => lIds, aFileName => 'TMP_LOG.TXT'); 
End; 
/

...含まれるIDを選択するフィルタを使用します。

+0

ありがとうアレックス!まさに私が探していたもの。従業員テーブルに何千もの行が格納されているとします。どのように私はそれらのIDのコレクションでevry単一のものをリストすることなくそれらを渡すのですか? – MrM

+0

@ user3651825 - これは選択する基準によって異なります。あなたの呼び出しブロックにクエリからコレクションを移入させ、それを渡すことができます。同じ行を取得するデモを追加しました。元のコールループに近いですが、IDを選択するために他の列を実際に使用している場合にのみ意味があります。 –

+0

私は、コレクションとユーザー定義のデータ型を扱う際に読んでおく必要があります。再度、感謝します!それ以上の質問はありません。 – MrM

関連する問題