【问题标题】:Getting an external table's location and file name?获取外部表的位置和文件名?
【发布时间】:2015-03-17 16:11:28
【问题描述】:

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

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

【问题讨论】:

标签: oracle plsql external-tables


【解决方案1】:

我不知道有什么方法可以在访问参数中捕获文件名。作为一种解决方法,您可以使用预处理器即时附加文件名,而不是修改原始文件。如果你有两个文件,比如包含a,b,1file_1.csv 和包含c,d,2file_2.csv,你可以有一个小的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;您可能需要测试一些,看看哪种方法在您的环境中效果最好(或足够快)。

【讨论】:

  • 看起来不错!干杯,我知道这可能是唯一的方法,但它的效率如何?例如如果我要在一个 5000 万条记录文件上运行它,是否需要相当长的时间才能进行即时追加?
  • @Dave - 比编辑文件的时间更少,因为它不需要写入磁盘,它都在内存中。但是这种逐行的方法对于大文件来说并不能很好地扩展。对于 150 万条记录文件,该脚本需要大约 80 秒来附加文件名。我添加了一个更快的sed 版本。
  • 完美,谢谢!我相信其他人会发现这很有用,因为网上似乎没有太多关于它的信息。
【解决方案2】:

您也许可以从all_external_locations DDL 中提取该数据。它包含创建表时指定的目录名称和位置参数。

【讨论】:

  • all_external_tables 包含定义的访问参数,但不包含位置,因为它位于访问参数块之外。
  • @Dave - 我更新了我的答案。看起来有一个 all_external_locations 这正是您所需要的。
  • 干杯我可以看到这对于单个文件是如何工作的,但是对于多个文件,您将无法区分哪些记录来自哪个文件。例如LOCATION(DMPDIR:'employee.dat', 'employee2.dat') 你怎么知道哪些记录来自哪个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 2010-11-03
相关资源
最近更新 更多