Oracle PLSQL數據導出csv的案例


  之前項目運維人員碰到一個問題,需要寫一個存儲過程,把數據導出為csv文件,查了一些資料,幫他寫成了一個PLSQL,今天拿出來分享一下,不足之處,歡迎指教。

數據背景:  用到兩張表,一張存放單位組織名稱org_name,它只有一個字段org_name;一張存放要導出的具體數據ryxx,其中ryxx這張表有一個字段是org_name中的org_name字段(需要like '%org_name%')。(表因為一些原因不能貼出來,見諒)

目標需求:  要求根據單位組織名稱即org_name,分批導出ryxx數據為csv文件,並且導出的文件最大不能超過30000行,文件名為單位組織名稱后跟序號

所用知識:  PLSQL語法,包括游標、循環、條件等語句,CSV文件導出語法

具體實現:  

  --1、創建要導出文件的存放地址的變量

  CREATE OR REPLACE DIRECTORY mydir AS 'D:\sjdc';

  --2、PLSQL開始

  DECLARE

    -- 定義游標 org 用於獲取組織名稱

    CURSOR org IS SELECT org_name FROM org_name;

    -- 定義組織名 org_name, 接收組織名

    org_name VARCHAR2(40);

    -- 定義組織名相似匹配(用於 LIKE 查詢)

    org_name_like VARCHAR(40);

    -- 定義總量,接收每次根據組織名稱查詢時 ryxx 表中匹配的數據總量

    count_number NUMBER;

    -- 定義每個組織名稱關聯的數據需要循環次數(因為每次導出只能導出30000條數據,需要多次導出)

    loop_times NUMBER;

    -- 定義當前循環到第幾次(同上)

    loop_i NUMBER;

    -- 定義根據 org_name 匹配查詢出的具體數據,為SYS_REFCURSOR類型,即動態游標

    data_cur SYS_REFCURSOR;

    -- 定義匹配查詢出的具體數據的總量(同上)

    count_cur SYS_REFCURSOR;

    -- 定義文件輸出

    csv_output UTL_FILE.FILE_TYPE;

    -- 定義 ryxx 的行類型

    data_row ryxx%ROWTYPE;

    -- 每個文件導出的最大行數

    MAX_LINE NUMBER := 30000;

    -- 輸出位置

    dir VARCHAR(20) := 'MYDIR';

  -- 函數體開始

  BEGIN

    -- 1、打開 org 游標,獲取組織名稱,挨個取出名稱進行操作

    OPEN org;

      LOOP

        --  2、循環取出組織名稱,當無數據時推出循環

        FETCH org INTO org_name;

        EXIT WHEN org%NOTFOUND;

        -- 3、拼接相似查詢的 org_name_like,兩邊都有%

        org_name_like := '%' || org_name || '%';

        -- 4、打開游標 count_cur, 查詢對應的單位名稱下的 ryxx 總量

        OPEN count_cur FOR 'SELECT COUNT(*) FROM ryxx WHERE st_code_name like :org_name_like' USING org_name_like;

          FETCH count_cur INTO count_number;

        CLOSE count_cur;

        -- 5、 計算此單位的數據總共需要導出幾次

        loop_times := count_number/MAX_LINE;

        -- 6、 開始循環導出數據

        loop_i := 0;

        LOOP

          -- 退出循環條件:當前循環次數大於總共要循環的次數

          EXIT WHEN loop_i > loop_times;

          

          IF loop_i <= loop_times THEN

            -- 7、打開查詢數據的data_cur游標,導出數據(需要分頁查詢,所以外層不能直接用*,否則不能把數據放入data_row)

            OPEN data_cur FOR 'SELECT id, name, age FROM

                (SELECT t.*, rownum rn FROM ryxx WHERE ST_CODE_NAME LIKE :org_name_like)

                WHERE rn <= ' || TO_CHAR((loop_i) * MAX_LINE) || ' AND rn > ' || TO_CHAR(loop_i * MAX_LINE) USING org_name_like;

              csv_output := UTL_FILE.FOPEN('MYDIR', org_name || loop_i || '.csv', 'W', MAX_LINE);

              LOOP

                FETCH data_cur INTO data_row;

                EXIT WHEN data_cur%NOTFOUND;

                UTL_FILE.PUT_LINE(CSV_OUTPUT, data_row.id || ',' || data_row.name || ',' || data_row.age);

              END LOOP;

              loop_i := loop_i + i;

              UTL_FILE.FCLOSE(csv_output);

            CLOSE data_cur;

          END IF;          

        END LOOP;

      END LOOP;

    CLOSE org;

  END;

  /

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM