使用 UTL_FILE 循环将数据写入平面文件
Write data to flat file in a loop using UTL_FILE
我正在尝试将 table 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
是为 table 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;
您需要在您的过程中执行循环,正如您代码中的注释已经建议的那样,而不是在您调用该过程时。但这意味着您需要传入多个 ID。如果您被允许创建新的用户定义类型,一个简单的方法是使用 table 集合:
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;
/
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 的任何过滤器。
我正在尝试将 table 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
是为 table 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;
您需要在您的过程中执行循环,正如您代码中的注释已经建议的那样,而不是在您调用该过程时。但这意味着您需要传入多个 ID。如果您被允许创建新的用户定义类型,一个简单的方法是使用 table 集合:
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;
/
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 的任何过滤器。