UTL_FILE 加载文件处理

本文介绍了一个PL/SQL过程,用于从指定路径和文件名的文件中读取数据,并将其加载到数据库表中。该过程使用UTL_FILE包进行文件操作,并通过字符串处理函数来解析每一行的数据。

create or replace procedureloadfiledata(p_path varchar2,p_filename varchar2) as

  v_filehandle    utl_file.file_type; --定义一个文件句柄

  v_text           varchar2(100); --存放文本

  v_name           test_loadfile.name%type;  --名称

  v_addr_jd     test_loadfile.addr_jd%type;  --存储地址

  v_region         test_loadfile.region%type; --存储内容

  v_firstlocation  number;

  v_secondlocation number;

begin

  if (p_path is null or p_filename is null) then

    goto to_end;

  end if;

  /*open   specified  file*/

  v_filehandle := utl_file.fopen(p_path, p_filename, 'r'); --r:表示读的权限

  loop

          begin

            utl_file.get_line(v_filehandle, v_text);

          exception

            when no_data_found then

              exit;

          end;

           v_firstlocation := instr(v_text, ',', 1, 1);

           v_secondlocation := instr(v_text, ',', 1, 2);

           v_name           := substr(v_text, 1, v_firstlocation - 1);

           v_addr_jd        := substr(v_text, v_firstlocation + 1, v_secondlocation - v_firstlocation - 1);

           v_region         := substr(v_text, v_secondlocation + 1);

          /*插入数据库操作*/

          insert into test_loadfilevalues (v_name, v_addr_jd,v_region);

          commit;

  end loop;

  <<to_end>>

  null;

end loadfiledata;
CREATE OR REPLACE DIRECTORY STOCK_DIR AS 'C:\Users\谢东杰\Desktop\数据库'; GRANT READ, WRITE ON DIRECTORY STOCK_DIR TO scott; CREATE TABLE stock_data ( 2 trade_date DATE, -- 交易日期 3 open_price NUMBER(10,2), -- 开盘价 4 close_price NUMBER(10,2), -- 收盘价 5 high_price NUMBER(10,2), -- 最高价 6 low_price NUMBER(10,2), -- 最低价 7 volume NUMBER(12) -- 成交量 8 ); DECLARE file_handle UTL_FILE.FILE_TYPE; v_line VARCHAR2(4000); row_count NUMBER := 0; v_date_raw VARCHAR2(20); v_open_raw VARCHAR2(20); v_high_raw VARCHAR2(20); v_low_raw VARCHAR2(20); v_close_raw VARCHAR2(20); v_volume_raw VARCHAR2(20); -- 解析后字段变量 v_date DATE; v_open NUMBER(10,2); v_high NUMBER(10,2); v_low NUMBER(10,2); v_close NUMBER(10,2); v_volume NUMBER(12); BEGIN -- 正确调用 FOPEN(参数顺序:目录对象名, 文件名, 打开模式, 最大行大小) file_handle := UTL_FILE.FOPEN('STOCK_DIR', '000001.SS.csv', 'R', 32767); -- 跳过标题行(如果存在) BEGIN UTL_FILE.GET_LINE(file_handle, v_line); EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END; -- 主循环:逐行读取并解析 LOOP BEGIN UTL_FILE.GET_LINE(file_handle, v_line); -- 使用正则表达式提取前6列(兼容末尾多余逗号) v_date_raw := REGEXP_SUBSTR(v_line, '([^,]*)(,|$)', 1, 1, NULL, 1); v_open_raw := REGEXP_SUBSTR(v_line, '([^,]*)(,|$)', 1, 2, NULL, 1); v_high_raw := REGEXP_SUBSTR(v_line, '([^,]*)(,|$)', 1, 3, NULL, 1); v_low_raw := REGEXP_SUBSTR(v_line, '([^,]*)(,|$)', 1, 4, NULL, 1); v_close_raw := REGEXP_SUBSTR(v_line, '([^,]*)(,|$)', 1, 5, NULL, 1); v_volume_raw := REGEXP_SUBSTR(v_line, '([^,]*)(,|$)', 1, 6, NULL, 1); -- 解析日期(格式:YYYY-MM-DD) BEGIN v_date := TO_DATE(v_date_raw, 'YYYY-MM-DD'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('[错误] 日期解析失败: ' || v_date_raw); RAISE; END; -- 解析数值字段(处理NULL和空字符串) v_open := CASE WHEN v_open_raw IN ('null', 'NULL', '') THEN NULL ELSE TO_NUMBER(v_open_raw) END; v_high := CASE WHEN v_high_raw IN ('null', 'NULL', '') THEN NULL ELSE TO_NUMBER(v_high_raw) END; v_low := CASE WHEN v_low_raw IN ('null', 'NULL', '') THEN NULL ELSE TO_NUMBER(v_low_raw) END; v_close := CASE WHEN v_close_raw IN ('null', 'NULL', '') THEN NULL ELSE TO_NUMBER(v_close_raw) END; v_volume := CASE WHEN v_volume_raw IN ('null', 'NULL', '') THEN NULL ELSE TO_NUMBER(v_volume_raw) END; -- 插入数据并累加计数器 INSERT INTO stock_data VALUES (v_date, v_open, v_close, v_high, v_low, v_volume); row_count := row_count + 1; DBMS_OUTPUT.PUT_LINE('[成功] 插入: ' || v_date || ' | 成交量: ' || v_volume); EXCEPTION WHEN NO_DATA_FOUND THEN EXIT; -- 文件读取完毕 WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('[错误] 行内容: ' || v_line); DBMS_OUTPUT.PUT_LINE('[错误] 详细: ' || SQLERRM); -- 仅跳过错误行,继续执行 END; END LOOP; -- 关闭文件并提交事务 UTL_FILE.FCLOSE(file_handle); COMMIT; DBMS_OUTPUT.PUT_LINE('[完成] 共插入 ' || row_count || ' 行数据'); EXCEPTION WHEN UTL_FILE.INVALID_PATH THEN DBMS_OUTPUT.PUT_LINE('[错误] 路径无效,请检查目录对象'); WHEN UTL_FILE.INVALID_OPERATION THEN DBMS_OUTPUT.PUT_LINE('[错误] 文件操作失败,检查权限或文件是否存在'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('[严重错误] 代码: ' || SQLCODE || ' | 信息: ' || SQLERRM); -- 尝试提交已插入的有效数据 IF row_count > 0 THEN COMMIT; DBMS_OUTPUT.PUT_LINE('[警告] 已提交 ' || row_count || ' 行有效数据'); END IF; RAISE; END; /以上代码虽然得到了正确结果,但是太长,请问能否简化
05-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值