在 PL/SQL 中读取大型 csv 文件

Reading large csv files in PL/SQL

Whosebug 上的第一个问题。

所以,我正在处理一个新项目,我需要从 PL/SQL 读取类似 CSV 的大型文件并将数据插入 table。这些文件每个大约有 400k 行,我不确定执行此操作的最佳方法。我在 PL/SQL 方面的专业知识对于这项任务来说有点短 :D

我见过有人使用 UTL_FILE.FOPEN。有没有一种方法可以分块读取大文件或使用更合适的工具?关于这个问题,我找不到任何有用的 post。

提前致谢!

您可以使用内联外部 table 或 APEX_DATA_PARSER 加载数据文件。这些技术通常比创建外部 table 更好,因为您不必管理那么多的架构对象。这些技术通常比使用像 sqlldr 这样的工具更好,因为这样你的程序就不会依赖于特定的外部程序、shell 脚本或操作系统。

内联外部Table

找到存放文件的目录:

select directory_path from all_directories where directory_name = 'DATA_PUMP_DIR';

在该目录中创建文件 test.csv:

Name,Salary
Alice,100
Bob,200

读取该文件而不创建外部文件table:

select *
from external
(   
    (
        name varchar2(100),
        salary number
    )
    default directory data_pump_dir
    access parameters
    (
        records delimited by newline
        skip 1
        fields terminated by ','
    )
    location ('test.csv')
);

结果:

NAME    SALARY
-----   ------
Alice   100
Bob     200

APEX_DATA_PARSER

如果您的数据库上安装了 APEX,APEX_DATA_PARSER 包是查询文件的便捷方式。尽管此技术确实需要安装一个 PL/SQL 对象,该对象会将文件加载到 blob 中。有关函数 FILE_TO_BLOB.

背后的代码,请参阅 this Oracle-Base article
select col001 name, col002 salary
from table
(
    apex_data_parser.parse
    (
        p_content   => file_to_blob('DATA_PUMP_DIR', 'test.csv'),
        p_file_name => 'test.csv'
    )
)

SQL 或 PL/SQL?

虽然您要求 PL/SQL 解决方案,但上述解决方案大多只是 SQL。但如果您甚至可以避免创建 PL/SQL 个对象,那也是一件好事。

如果您要在 PL/SQL 中使用此代码,将这些 select 语句放在这样的循环中是微不足道的:

begin
    for lines in
    (
        select *
        from external
        (   
            (
                name varchar2(100),
                salary number
            )
            default directory data_pump_dir
            access parameters
            (
                records delimited by newline
                skip 1
                fields terminated by ','
            )
            location ('test.csv')
        )
    ) loop
        --Do something with the results here.
        dbms_output.put_line('Name: '||lines.name||',Salary: '||lines.salary);
    end loop;
end;
/