代码之家  ›  专栏  ›  技术社区  ›  Matt Damon

获取外部表的位置和文件名?

  •  4
  • Matt Damon  · 技术社区  · 9 年前

    我正在处理多个文件作为外部表的一部分。是否有任何方法可以获取正在外部表中处理的文件名并将其放入表中?

    目前,我能找到的唯一解决方案是将文件名附加到平面文件中的每个记录,这从效率的角度来看并不理想,并且涉及修改原始数据。当然,外部表随时都知道正在处理的文件是什么?

    2 回复  |  直到 9 年前
        1
  •  4
  •   Alex Poole    9 年前

    我不知道在访问参数中捕获文件名的任何方法。作为一种变通方法,您可以使用预处理器来动态追加文件名,而不是修改原始文件。如果你有两个文件,说 file_1.csv 包含 a,b,1 file_2.csv 包含 c,d,2 ,你可以有一个小的shell脚本 append_filename.sh :

    #!/bin/bash
    while read line
    do
      printf "%s,%s\n" "${line}" "${1##*/}"
    done < $1
    

    您可以通过直接调用脚本来验证它是否有帮助:

    $ ./append_filename.sh file_1.csv
    a,b,1,file_1.csv
    

    然后可以定义外部表,通过 the preprocessor clause ,类似于:

    create table e42 (
      col1 varchar2(10),
      col2 varchar2(10),
      col3 number,
      filename varchar2(30)
    )
    organization external (
      type oracle_loader
      default directory d42
      access parameters (
        records delimited by newline
        preprocessor 'append_filename.sh'
        fields terminated by ','
      )
      location ('file_1.csv', 'file_2.csv')
    );
    
    Table E42 created.
    

    然后自动拾取文件名:

    select * from e42;
    
    COL1       COL2             COL3 FILENAME                     
    ---------- ---------- ---------- ------------------------------
    a          b                   1 file_1.csv                    
    c          d                   2 file_2.csv                    
    

    我已经删除了目录路径,所以您只能看到文件名-如果您愿意,可以保留完整路径,但这可能不是必要的,并且可能会向只能查询表的人透露操作系统的详细信息。笔记 the security guidelines ; 我在这里通过对所有内容使用一个目录来保持简单,但您应该将预处理器放在其他地方。当然,这是假设一个Unix-y平台或GNU工具;如果您使用的是Windows,则批处理文件也可能有类似的功能。


    对于大型文件,这种逐行读取的方法相对较慢;在我的平台上,添加文件名的150万行测试文件花费了大约80秒。其他内置工具将更快;此版本具有 sed 对于同一个文件,只需一秒钟多一点:

    #!/bin/bash
    sed -e 's!$!,'"${1##*/}"'!' $1
    

    您可以尝试其他选择,例如 awk 也您可能需要测试一些,以了解在您的环境中什么最有效(或足够快)。

        2
  •  2
  •   Mr. Llama    9 年前

    您可以从 all_external_locations 日期。它包含创建表时指定的目录名和位置参数。