1. 程式人生 > >PL/SQL-- UTL FILE包的使用介紹

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檔案的目錄  [email protected]> ho mkdir -p /u03/database/usbo/db_utl_dir    --在資料庫層面新增directory  [email protected]> create directory db_utl_dir as '/u03/database/usbo/db_utl_dir';    --許可權授予  [email protected]> 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.  --檢視產生的檔案  [email protected]> ho more /u03/database/usbo/db_utl_dir/emp.txt  JONES,MANAGER  BLAKE,MANAGER  CLARK,MANAGER  SCOTT,ANALYST  KING,PRESIDENT  FORD,ANALYSTc、從資料檔案讀入並寫入到表  [email protected]> create table tb_emp(val varchar2(30), file_name varchar2(10));    [email protected]> exec read_demo('emp.txt','db_utl_dir');  -->呼叫過程來實現,程式碼見文章尾部    PL/SQL procedure successfully completed.    [email protected]> 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、讀寫混合模式示例  [email protected]> set serveroutput on[email protected]> exec rw_demo;     -->呼叫過程來實現,程式碼見文章尾部  14  14  28  42  56  71  84    PL/SQL procedure successfully completed.    [email protected]> ho ls   out.txt  x.txt    [email protected]> ho more out.txt  JONES,MANAGER  JONES,MANAGER  BLAKE,MANAGER  CLARK,MANAGER  SCOTT,ANALYST  KING,PRESIDENT  FORD,ANALYSTe、演示中用到的過程  --下面是讀模式的過程程式碼  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

Oracle 牛鵬社    Oracle DBsupport

更多參考