【问题标题】:Find missing dates by comparing two columns in Table and View using PL/SQL通过使用 PL/SQL 比较表和视图中的两列来查找缺失的日期
【发布时间】:2021-01-15 12:05:08
【问题描述】:

我必须比较表和视图中可用的日期列,表中任何缺失的日期都会从视图中添加记录。表和视图都有 1 亿条数据。我已经编写了下面的代码,但是要迭代超过 400K 行,表格和视图每个需要 2 小时。想知道我是否可以改进我的代码进行比较。请不要问我为什么要从视图中添加记录到表中,这是一个有点复杂的设置,我无能为力。

注意-

  1. 我必须为大约 100 多张桌子运行这个。
  2. 不同的表格/视图有不同的日期格式。但我们将与之进行比较的表和相应视图保持不变。
  3. 在某些表中存在无效日期,应忽略这些记录。如果异常仍在继续,我通过在代码中使用 TO_DATE 函数来实现这一点。
  4. 每个表/视图的日期格式都保存在 MASTER 表中。

不包括使用 BEGIN 和 DECLARE 读取 MASTER 表的初始代码

    query_str := 'select DISTINCT ' || date_column_name || ' as DATM FROM ' || tablename;
    OPEN c_query FOR query_str;

    LOOP
        BEGIN
            FETCH c_query INTO dateval;
            EXIT WHEN c_query%notfound;
            tmp := TO_DATE(
                dateval,
                dateformat
            );
            tabledatelist(dateval) := 'Date Val';
        EXCEPTION
            WHEN OTHERS THEN
                continue;
        END;
    END LOOP;

    CLOSE c_query;
    query_str := 'select DISTINCT ' || date_column_name || ' as DATM FROM ' || viewname;
    OPEN c_query FOR query_str;

    LOOP
        BEGIN
            FETCH c_query INTO dateval;
            EXIT WHEN c_query%notfound;
            tmp := TO_DATE(
                dateval,
                dateformat
            );
            IF
                NOT tabledatelist.EXISTS(dateval)
            THEN
                -- Code to add missing records. Using it as Insert into select col_name from table.
            END IF;

        EXCEPTION
            WHEN OTHERS THEN
                continue;
        END;
    END LOOP;

    CLOSE c_query;

【问题讨论】:

  • 您不应该将日期存储在 varchar 列中。在继续之前,您是否有机会修复损坏的设计。

标签: oracle plsql oracle19c


【解决方案1】:

数百万行的循环很慢。你为什么不完全跳过它们并做这样的事情呢?

insert into tablename (date_column_name)
select date_column_name from viewname
minus
select date_column_name from tablename;

我猜这段代码缺少很多信息(附加列),但是嘿 - 你也没有发布它们。所以 - 看看这样的原则是否可行。如果它必须是动态 SQL(因为您有 100 多个表),那就这样吧。但是,我推测并希望它会表现得更好。


截至无效日期:嗯,这就是将日期存储为字符串的成本。

一种选择可能是创建一个返回例如 function 1(如果日期有效)或 0(如果无效)。你会用它作为

select date_column_name from viewname 
where f_date_valid(date_column_name) = 1

但它会影响性能。

也许你可以分两步完成:

  • 首先插入所有缺失的日期(包括无效日期)
  • 然后删除日期无效的行

不过,我认为无论您采用哪种方法,性能都会受到影响,并且所有这些因为您将日期存储为字符串......糟糕,糟糕的想法。我不是说它是你的(可能不是)。

【讨论】:

  • 使用这种方法如何忽略日期无效的记录?我的意思是某些表的格式为 YYYYMMDDHH24MISS,但值为 00000100000000。您要我遍历上述查询的结果并对其使用 TO_DATE 函数吗?
  • 我编辑了答案;请看一下。
  • 这里使用的是Oracle 19c,所以可以使用内置的validate_conversion docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/…
  • 更好!我(大部分)仍在使用 11g,很少使用 12c,甚至从未见过 19c。谢谢你,@Andrew,希望 OP 能够使用它。
  • 非常感谢。以上所有投入都帮助我减少了大量工作时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-08
  • 2022-09-27
  • 2016-07-25
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
  • 2020-12-12
相关资源
最近更新 更多