使用UTL_FILE

时间:2016-09-07 09:57:35

标签: oracle plsql oracle11g utl-file

我正在尝试将表employees中的员工姓名导出为平面文件。平面文件应具有以下结构:

HEADER 
DETAILS JACK
DETAILS JUNE
TRAILER

我正在努力的是如何在循环中运行它以将名称存储在同一文件中的单行中。我当前的脚本只将一个名称一次导出到单独的文件中。由于文件名保持不变,因此每次执行过程都会覆盖文件。

请注意,如果可能,我希望将文件名作为变量。

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 个答案:

答案 0 :(得分:2)

您需要在程序中执行循环,因为代码中的注释已经建议,而不是在调用过程时。但这意味着您需要传入多个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;
/

然后用一组ID调用它,使用相同的UDT:

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

with生成一个包含以下内容的文件:

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的任何过滤器。