PL/SQL-->UTL_FILE包的使用介绍

    在PL/SQL中,UTL_FILE包提供了文本文件输入和输出互功能。也就是说我们可以通过该包实现从操作系统级别来实现文件读取输入或者是写入到操作系统文件。通过该包也可以将其他系统的数据加载到数据库中。如加载web服务器日志,用户登录数据库日志乃至Oracle日志文件等等。本文主要描述了UTL_FILE的功能以及通过实例演示并理解这个包下相关过程函数的用法。

 

1、UTL_FILE介绍
   a、实现基于操作系统级别的读取与写入功能
   b、该方式为基于服务器端的文本文件访问模式,不支持二进制文件
   c、可以通过设置参数utl_file_dir来设置pl/sql访问操作系统文件的多个路径
   d、所有用户可以读写utl_file_dir参数设定的目录,因此应考虑安全问题
   e、也可以将参数utl_file_dir置空,而通过创建directory以及授予对directory权限来进行访问os文件(推荐方式)

 

2、UTL_FILE包中的过程和函数
a、UTL_FILE中定义的file_type为记录类型,如下所示其成员是私有的,不能够被直接引用或改变这个记录的组件。

   TYPE file_type IS RECORD (
      id          BINARY_INTEGER,
      datatype    BINARY_INTEGER,
      byte_mode   BOOLEAN);

b、UTL_FILE中相关过程函数的功能说明
   FCLOSE Procedure            Closes a file
   FCLOSE_ALL Procedure        Closes all open file handles
   FCOPY Procedure             Copies a contiguous portion of a file to a newly created file
   FFLUSH Procedure            Physically writes all pending output to a file
   FGETATTR Procedure          Reads and returns the attributes of a disk file
   FGETPOS Function            Returns the current relative offset position within a file, in bytes
   FOPEN Function              Opens a file for input or output
   FOPEN_NCHAR Function        Opens a file in Unicode for input or output
   FREMOVE Procedure           Deletes a disk file, assuming that you have sufficient privileges
   FRENAME Procedure           Renames an existing file to a new name, similar to the UNIX mv function
   FSEEK Procedure             Adjusts the file pointer forward or backward within the file by the number of bytes specified
   GET_LINE Procedure          Reads text from an open file
   GET_LINE_NCHAR Procedure    Reads text in Unicode from an open file
   GET_RAW Procedure           Reads a RAW string value from a file and adjusts the file pointer ahead by the number of bytes read
   IS_OPEN Function            Determines if a file handle refers to an open file
   NEW_LINE Procedure          Writes one or more operating system-specific line terminators to a file
   PUT Procedure               Writes a string to a file
   PUT_LINE Procedure          Writes a line to a file, and so appends an operating system-specific line terminator
   PUT_LINE_NCHAR Procedure    Writes a Unicode line to a file
   PUT_NCHAR Procedure         Writes a Unicode string to a file
   PUTF Procedure              A PUT procedure with formatting
   PUTF_NCHAR Procedure        A PUT_NCHAR procedure with formatting, and writes a Unicode string to a file, with formatting
   PUT_RAW Procedure           Accepts as input a RAW data value and writes the value to the output buffer

 

3、演示ULT_FILE用法

a、使用UTL_FILE的主要步骤(使用directory方式)
  --先创建用于存放os文件的目录
  scott@USBO> ho mkdir -p /u03/database/usbo/db_utl_dir

  --在数据库层面添加directory
  scott@USBO> create directory db_utl_dir as '/u03/database/usbo/db_utl_dir';

  --权限授予
  scott@USBO> grant read,write on directory db_utl_dir to public;

b、从SQL查询写入到数据文件
  DECLARE
     vsfile   UTL_FILE.file_type;  --->定义用于接收文件句柄的类型
     v_cnt    PLS_INTEGER := 0;
  BEGIN
     vsfile :=
        UTL_FILE.fopen ('DB_UTL_DIR',  --->使用fopen打开文件,定义了文件路径,文件名,读写方式以及每一行字符的最大长度,缺省为1024
                        'emp.txt',
                        'W',
                        200);

     FOR i IN (SELECT t.ename || ',' || t.job AS msg    --->使用了一个for循环来读取scott.emp表
                 FROM scott.emp t WHERE t.sal>2000)
     LOOP
        UTL_FILE.put_line (vsfile, i.msg);              --->将for循环查询的内容使用put_line写入到文件
        v_cnt := v_cnt + 1;                             --->计数器,用于统计写入的记录数
     END LOOP;

     UTL_FILE.fflush (vsfile);
     UTL_FILE.fclose (vsfile);
     DBMS_OUTPUT.put_line (v_cnt || ' rows unloaded');
  END;
  /

  6 rows unloaded

  PL/SQL procedure successfully completed.

  --查看产生的文件
  scott@USBO> ho more /u03/database/usbo/db_utl_dir/emp.txt
  JONES,MANAGER
  BLAKE,MANAGER
  CLARK,MANAGER
  SCOTT,ANALYST
  KING,PRESIDENT
  FORD,ANALYST

c、从数据文件读入并写入到表
  scott@USBO> create table tb_emp(val varchar2(30), file_name varchar2(10));

  scott@USBO> exec read_demo('emp.txt','db_utl_dir');  -->调用过程来实现,代码见文章尾部

  PL/SQL procedure successfully completed.

  scott@USBO> select * from tb_emp;

  VAL                           FILE_NAME
  ----------------------------- ---------------------
  JONES,MANAGER                 emp.txt
  BLAKE,MANAGER                 emp.txt
  CLARK,MANAGER                 emp.txt
  SCOTT,ANALYST                 emp.txt
  KING,PRESIDENT                emp.txt
  FORD,ANALYST                  emp.txt

  6 rows selected.

d、读写混合模式示例
  scott@USBO> set serveroutput on;
  scott@USBO> exec rw_demo;     -->调用过程来实现,代码见文章尾部
  14
  14
  28
  42
  56
  71
  84

  PL/SQL procedure successfully completed.

  scott@USBO> ho ls
  out.txt  x.txt

  scott@USBO> ho more out.txt
  JONES,MANAGER
  JONES,MANAGER
  BLAKE,MANAGER
  CLARK,MANAGER
  SCOTT,ANALYST
  KING,PRESIDENT
  FORD,ANALYST

e、演示中用到的过程
  --下面是读模式的过程代码
  CREATE OR REPLACE PROCEDURE read_demo (file_name_in VARCHAR2, utl_dir_in VARCHAR2)
  --两个传入参数,一个用于指定文件名,一个用于指定utl_file_dir目录
  --Author : Leshami
  --Blog   : http://blog.csdn.net/leshami
  IS
     vsfile      UTL_FILE.file_type;
     vnewline    VARCHAR2 (200);
     v_utl_dir   VARCHAR2 (30);
  BEGIN
     v_utl_dir := UPPER (utl_dir_in);
     vsfile := UTL_FILE.fopen (v_utl_dir, file_name_in, 'r');   --->打开文件

     IF UTL_FILE.is_open (vsfile)
     THEN
        LOOP
           BEGIN
              UTL_FILE.get_line (vsfile, vnewline);   -->从文件读入行

              IF vnewline IS NULL
              THEN
                 EXIT;
              END IF;

              INSERT INTO tb_emp (val, file_name)     --->将读入的行插入到表
                   VALUES (vnewline, file_name_in);
           EXCEPTION
              WHEN NO_DATA_FOUND
              THEN
                 EXIT;
           END;
        END LOOP;

        COMMIT;
     END IF;

     UTL_FILE.fclose (vsfile);                       --->关闭打开的文件
     UTL_FILE.frename (v_utl_dir,                    --->此处进行了重命名
                       file_name_in,
                       v_utl_dir,
                       'x.txt',
                       TRUE);
  EXCEPTION                                          --->定义了相关的异常信息
     WHEN UTL_FILE.invalid_mode
     THEN
        raise_application_error (-20051, 'Invalid Mode Parameter');
     WHEN UTL_FILE.invalid_path
     THEN
        raise_application_error (-20052, 'Invalid File Location');
     WHEN UTL_FILE.invalid_filehandle
     THEN
        raise_application_error (-20053, 'Invalid Filehandle');
     WHEN UTL_FILE.invalid_operation
     THEN
        raise_application_error (-20054, 'Invalid Operation');
     WHEN UTL_FILE.read_error
     THEN
        raise_application_error (-20055, 'Read Error');
     WHEN UTL_FILE.internal_error
     THEN
        raise_application_error (-20057, 'Internal Error');
     WHEN UTL_FILE.charsetmismatch
     THEN
        raise_application_error (-20058, 'Opened With FOPEN_NCHAR
      But Later I/O Inconsistent');
     WHEN UTL_FILE.file_open
     THEN
        raise_application_error (-20059, 'File Already Opened');
     WHEN UTL_FILE.invalid_maxlinesize
     THEN
        raise_application_error (-20060, 'Line Size Exceeds 32K');
     WHEN UTL_FILE.invalid_filename
     THEN
        raise_application_error (-20061, 'Invalid File Name');
     WHEN UTL_FILE.access_denied
     THEN
        raise_application_error (-20062, 'File Access Denied By');
     WHEN UTL_FILE.invalid_offset
     THEN
        raise_application_error (-20063, 'FSEEK Param Less Than 0');
     WHEN OTHERS
     THEN
        raise_application_error (-20099, 'Unknown UTL_FILE Error');
  END read_demo;
  /

  --下面是读写模式过程的代码,这个过程实现了从一个数据文件读出并写入到另外一个数据文件
  CREATE OR REPLACE PROCEDURE rw_demo
  IS
     infile     UTL_FILE.file_type;
     outfile    UTL_FILE.file_type;
     vnewline   VARCHAR2 (4000);
     i          PLS_INTEGER;
     j          PLS_INTEGER := 0;
     seekflag   BOOLEAN := TRUE;
  BEGIN
     -- open a file to read
     infile := UTL_FILE.fopen ('DB_UTL_DIR', 'x.txt', 'r');       -->打开源文件用于读取数据
     -- open a file to write
     outfile := UTL_FILE.fopen ('DB_UTL_DIR', 'out.txt', 'w');   -->创建目标文件用于存放数据

     -- if the file to read was successfully opened
     IF UTL_FILE.is_open (infile)
     THEN
        -- loop through each line in the file
        LOOP
           BEGIN
              UTL_FILE.get_line (infile, vnewline);                   -->从源文件读取行

              i := UTL_FILE.fgetpos (infile);                      -->将行的位置赋值并输出
              DBMS_OUTPUT.put_line (TO_CHAR (i));

              UTL_FILE.put_line (outfile, vnewline, FALSE);  -->将得到的数据行写出到文件句柄缓冲
              UTL_FILE.fflush (outfile);                        -->将数据行从缓冲区写入到文件

              IF seekflag = TRUE
              THEN
                 UTL_FILE.fseek (infile, NULL, -30);            -->用于调整文件指针,即偏移量
                 seekflag := FALSE;
              END IF;
           EXCEPTION
              WHEN NO_DATA_FOUND
              THEN
                 EXIT;
           END;
        END LOOP;

        COMMIT;
     END IF;

     UTL_FILE.fclose (infile);                                          -->关闭源文件
     UTL_FILE.fclose (outfile);                                        -->关闭目标文件
  EXCEPTION
     WHEN OTHERS
     THEN
        raise_application_error (-20099, 'Unknown UTL_FILE Error');
  END rw_demo;
  /

注意在使用UTL_FILE包用到DIRECTORY数据库对象时,名字一定要大写,否则会遭遇“ORA-29280: invalid directory path”错误
主要参考:
http://psoug.org/reference/utl_file.html http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/u_file.htm#BABGGEDF

   

更多参考

使用 DBMS_PROFILER 定位 PL/SQL 瓶颈代码

使用PL/SQL Developer剖析PL/SQL代码

对比 PL/SQL profiler 剖析结果

PL/SQL Profiler 剖析报告生成html

DML Error Logging 特性 

PL/SQL --> 游标

PL/SQL --> 隐式游标(SQL%FOUND)

批量SQL之 FORALL 语句

批量SQL之 BULK COLLECT 子句

PL/SQL 集合的初始化与赋值

PL/SQL 联合数组与嵌套表
PL/SQL 变长数组
PL/SQL --> PL/SQL记录

SQL tuning 步骤

高效SQL语句必杀技

父游标、子游标及共享游标

绑定变量及其优缺点

dbms_xplan之display_cursor函数的使用

dbms_xplan之display函数的使用

执行计划中各字段各模块描述

使用 EXPLAIN PLAN 获取SQL语句执行计划

时间: 2024-12-25 15:58:12

PL/SQL-->UTL_FILE包的使用介绍的相关文章

Oracle数据库之开发PL/SQL子程序和包

PL/SQL块分为匿名块与命名块,命名块又包含子程序.包和触发器. 过程和函数统称为PL/SQL子程序,我们可以将商业逻辑.企业规则写成过程或函数保存到数据库中,以便共享. 过程和函数均存储在数据库中,并通过参数与其调用者交换信息.过程和函数的唯一区别是函数总向调用者返回数据,而过程不返回数据. 1. 存储过程概念 存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中.经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名

Oracle中PL/SQL中if语句的写法介绍

以下是对Oracle中PL/SQL中if语句的写法进行了详细的分析介绍,需要的朋友可以过来参考下   复制代码 代码如下: /* If语句: 判断用户输入的数字. */ set serveroutput on --接收键盘输入 accept num prompt '请输入一个数字:'; declare   --将屏幕输入的数字付给变量   pnum number := # begin   if pnum = 0 then dbms_output.put_line('您输入的是0');   end

PL/SQL --> DBMS_DDL包的使用

--============================= -- PL/SQL --> DBMS_DDL包的使用 --=============================       为了便于建立性能良好的PL/SQL程序,Oracle提供了大量的系统包供使用.Oracle提供的这些包扩展并增强了数据库的一些功能,以及突 破了PL/SQL的一些限制.本文讲述了Oracle提供的包DBMS_DDL,以及其使用方法.   一.    使用DBMS_DDL包可以对包,包体,存储过程,函数,触

PL/SQL重新编译包无反应

前几天碰到一个有趣的事情:早上同事执行一个包很久没有反应,就中断了执行,发邮件让我帮忙查看具体情况,我用PL/SQL Developer登录后,找到这个包的过程中发现这个包的图标有红色叉叉,也就是说这个包有地方没有编译通过,于是我便单击右键点击"重新编译",结果一直没有响应,导致PL/SQL Developer直接卡死,刚开始没太留意,直接杀掉PL/SQL Developer相关进程,重新打开它然后编译这个包,结果还是这个情况,还是头一次遇到这种情况,一头雾水. 后来搜索了一下才知道原

Oracle中PL/SQL中if语句的写法介绍_oracle

复制代码 代码如下: /*If语句:判断用户输入的数字.*/set serveroutput on --接收键盘输入accept num prompt '请输入一个数字:'; declare   --将屏幕输入的数字付给变量  pnum number := #begin  if pnum = 0 then dbms_output.put_line('您输入的是0');  end if;   if pnum = 1 then dbms_output.put_line('您输入的是1'); 

[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七:   程序包的创建与应用(聪明在于学习,天才在于积累!) --通过知识共享树立个人品牌.     继上七篇:            [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)            [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,

[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)

原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)  [顶]ORACLE PL/SQL编程详解之二:   PL/SQL块结构和组成元素(为山九仞,岂一日之功)     继上四篇:ORACLE PL/SQL编程之八:把触发器说透                ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)                [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不

PL/SQL的进阶----编写分页过程

PL/SQL的进阶----编写分页过程 介绍 分页是任何一个网站(bbs,网上商城, blog)都会使用到的技术,因此学习 pl/sql 编程开发就一定要掌握该技术.   ①无返回值的存储过程 古人云:欲速则不达.首先是掌握最简单的存储过程,无返回值的存储过程: 案例:现在有一张表,字段有"书号,书名,出版社".请编写一个存储过程,可以向book表添加书,要求通过JAVA程序调用该过程. ----book表 SQL>create table book (boodId number

PL/SQL 游标变量

    游标变量与游标相似,有其共性,也有其不同点.就其共性来说两者都是指向多行查询的结果集中的当前行.都要经历声明,打开,检索与关闭的过程.所不同的是游标与游标变量类似于常量与变量.游标是静态的,而游标变量是动态的,因为游标变量并不与某个特定的查询相绑定.所以,游标变量可以打开任何类型兼容的查询.其次可以将游标变量作为参数传递给本地和存储子程序.本文主要描述游标变量的使用.   一.什么是游标变量    显示游标用于命名一个工作区域,其中保存多行查询的信息,而且该游标始终指向工作区域的内容.而