DB2/400 select * 有效,但 count(*) 无效

DB2/400 select * works, but count(*) does not

我在尝试检索保险系统的一些记录时遇到了一个奇怪的问题。 似乎当我说 select 时查询运行,但当我进行计数时它抱怨日期格式()。 一些背景知识,我们的日期以两种方式之一存储为整数(是的,我知道这很糟糕)。 YYMMDD 表示 2000 年之前的年份,CYYMMDD 表示 1999 年。

  1. 1999 年 10 月 21 日变为 991021
  2. 2000 年 10 月 21 日变为 1001021。

这是下面的代码,我已经评论了哪些有效以及无效时包含的错误。 大约 1980 年的 IBM 是一个执行不力的想法的妓院。

    -- returns rows correctly
select * from mudata.hdk01
where date(to_date(to_char(A08 + 19000000, '99999999'), 'YYYYMMDD')) < '01/01/1999'
fetch first 100 rows only;

-- refuses with error
-- java.sql.SQLException: [SQL0181] Value in date, time, or timestamp string not valid.
-- Query 1 of 1, Rows read: 0, Elapsed time (seconds) - Total: 0.093, SQL query: 0.093, Reading results: 0
select count(*) from mudata.hdk01
where date(to_date(to_char(A08 + 19000000, '99999999'), 'YYYYMMDD')) < '01/01/1999'
fetch first 100 rows only;

select count(*) 只会 return 1 行,所以 fetch first 100 rows only 没有影响。

所以您的第一个查询只读取了 100 行。

第二个查询正在读取所有行。在后面几行的某处,您的 A08 字段中有错误数据。

更好的解决方案是拥有一个用户定义函数 (UDF),您可以调用它来转换日期,这将允许您处理错误数据...returning NULL 或 return 一些有效的日期。

您可以推出自己的 UDF,或使用 Alan Campin 的开源 iDate

创建以下 SQL UDF:

CREATE OR REPLACE FUNCTION TO_DATE_SAFE (P_DT INT)
RETURNS DATE
DETERMINISTIC
NO EXTERNAL ACTION
BEGIN
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
    RETURN date(to_date(to_char(P_DT + 19000000, '99999999'), 'YYYYMMDD'));
END

并使用以下语句找到值违反规则的行:

select A08 
from mudata.hdk01
where to_date_safe(A08) is null and A08 is not null