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

Getting an external table's location and file name?

我正在处理多个文件作为外部 table 的一部分。有什么方法可以获取在外部 table 中处理的文件名并将其放在 table 中?

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

您可以从 all_external_locations DDL 中提取该数据。它包含创建 table.

时指定的目录名称和位置参数

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

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

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

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

然后您可以定义外部 table 以通过 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                    

我删除了目录路径,因此您只能看到文件名 - 如果您愿意,可以保留完整路径,但这可能不是必需的,并且可能会向只能知道的人透露 OS 详细信息查询table。注意the security guidelines;我在这里通过对所有内容使用一个目录来保持简单,但是您应该将预处理器放在其他地方。当然,这是假设一个 Unix-y 平台或 GNU 工具;如果您使用 Windows.

,批处理文件应该可以实现类似的功能

这种逐行读取的方式对于大文件会比较慢;在我的平台上,附加文件名的 150 万行测试文件花费了大约 80 秒。其他内置工具会更快;这个带有 sed 的版本对同一个文件只需要一秒多一点的时间:

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

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