2

我想使用外部表来加载 csv 文件,因为它非常方便,但问题是我如何确保我不会连续两次加载同一个文件?我无法验证加载的数据,因为它可能是与以前相同的信息;例如,我需要找到一种方法来确保用户不会加载与 2 小时前相同的文件。我想过每次上传不同名称的文件,然后发出alter table命令来更改外部表定义中的文件名,但这听起来有点冒险。我还考虑用序列标记文件中的每一行以帮助区分文件,但我怀疑客户端会接受它,因为他们需要手动执行此操作(文件从某处导出)。

有没有更好的方法来确保我不会在外部表中加载相同的文件,除了更改文件名并在表上执行更改?

谢谢

4

2 回答 2

0

我只能想到一个有点像这样的解决方案:

  1. 在数据文件名中编码一个时间戳(例如:YYYYMMDDHHMISS-file.csv),其中 YYYYMMDDHHMISS 是时间戳。
  2. 使用字段时间戳创建一个表(如上)。
  3. 创建一个 shell 脚本:
    • 从数据文件名中提取时间戳。
    • 使用时间戳作为参数调用 sqlscript,如果该时间戳不存在则返回 0,如果时间戳已经存在则返回 <>0,在这种情况下退出脚本并显示错误:文件:YYYYMMDDHHMISS-file.csv 已加载。
    • 将 YYYYMMDDDHHMISS-file.csv 复制到 input-file.csv。
    • 运行加载 input-file.csv 文件的 sql 加载程序脚本
    • 成功时:运行带有参数 timestamp 的第二个 sql 脚本,该脚本将记录插入数据库以指示文件已加载并将原始文件移动到备份文件夹。
    • when failure:报告加载脚本失败。
于 2016-12-07T01:51:43.317 回答
0

当您将数据从external table数据库中导入时,您可以使用MERGE命令而不是insert. 它让您不必担心重复数据

请参阅有关Oracle 合并命令的博客

更重要的是,我们可以将整个转换过程包装到这个Oracle MERGE命令中,引用外部表和一个命令中的表函数作为MERGED Oracle数据的来源。

    alter session enable parallel dml;
merge /*+ parallel(contract_dim,10) append */
    into contract_dim d
    using TABLE(trx.go(
        CURSOR(select /*+ parallel(contracts_file,10) full (contracts_file) */ *
            from contracts_file ))) f
    on  d.contract_id = f.contract_id 
    when matched then
        update set desc              = f.desc,
                   init_val_loc_curr = f.init_val_loc_curr,
                   init_val_adj_amt  = f.init_val_adj_amt
    when not matched then
        insert values ( f.contract_id,
                        f.desc,
                        f.init_val_loc_curr,
                        f.init_val_adj_amt);  

所以我们有了它——我们复杂的 ETL 函数都包含在一个 Oracle MERGE 语句中。没有单独的 SQL*Loader 阶段,没有暂存表,并且全部通过管道传输并并行加载

于 2015-11-20T10:42:12.720 回答