【问题标题】:external tables: how to make sure i don't load same file/data外部表:如何确保我不加载相同的文件/数据
【发布时间】:2015-11-20 09:37:07
【问题描述】:

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

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

谢谢

【问题讨论】:

  • 您如何仅根据文件名识别“相同文件” - 内容不同? capturing the filename 有用吗? (你可以做同样的事情来添加你的序列)。或者,您可以使用预处理器指令来查找未处理的文件并将其重命名为您的外部表期望的标准名称。然后后续查询将查找不同的文件。需要一些工作,但可能是可行的。
  • 客户(一家银行)说他们可以在早上和下午加载相同的数据,这是正确的。但他们需要确保他们不会错误地加载同一个文件,因此他们希望文件具有不同的名称
  • 如果他们提供不同名称的文件,并且您只想查看每个文件一次,那么将等待文件(可能是最旧/最新?)重命名为您的外部表期望的预处理器可能然后工作。第二次查看它时,它会查找不同的文件,因此您不会再看到相同的文件。较早的答案可能会给出一个起点。不幸的是,我现在没有时间整理一些东西......

标签: oracle csv plsql import external-tables


【解决方案1】:

当您将数据从external table 带到您的数据库时,您可以使用MERGE 命令而不是insert。它让你不用担心重复数据

查看关于The Oracle Merge Command的博客

更重要的是,我们可以把整个改造过程收起来 一个 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 阶段,没有 staging 表,并且全部通过管道并行加载

【讨论】:

  • 虽然您尝试解决xy problem,但我认为这不是 OP 的问题。看来他对重复记录没问题,只是重复文件是个问题。
  • 是的,florin 是对的,重复数据不是问题,它可能会发生。但我需要确保用户不会错误地连续两次加载同一个文件
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 2017-11-22
    • 2016-11-09
    • 1970-01-01
    相关资源
    最近更新 更多