我正在处理多个文件作为外部表的一部分。有什么办法可以让我在外部表中处理文件名并将其放在表中吗?
目前我能找到的唯一解决方案是将文件名附加到平面文件中的每个记录,从效率的角度来看这并不理想,并涉及修改原始数据。当然外部表可以随时知道正在处理哪个文件?
答案 0 :(得分:4)
我不知道在访问参数中捕获文件名的任何方法。作为一种解决方法,您可以使用预处理器动态附加文件名,而不是修改原始文件。如果您有两个文件,例如file_1.csv
包含a,b,1
和file_2.csv
包含c,d,2
,则可以使用append_filename.sh
这样的小型shell脚本:
#!/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
;你可能需要测试一些,看你的环境中哪种方法效果最好(或者足够快)。
答案 1 :(得分:0)
您可以从all_external_locations
DDL中提取该数据。它包含创建表时指定的目录名称和位置参数。