错误日期:SQL 服务器提供 ISDATE(),但 Informix 不提供。是否有同等的解决方法?

Bad Dates: SQL Server Offers ISDATE(), But Informix Does Not. Is There an Equal Workaround?

我正在处理遗留的 Informix 数据,显然在输入时从未正确验证过。

这意味着 DATE 字段可以包含

以下在 SQL 服务器中运行良好:

SELECT
    COUNT(1) AS [Grand Total Count of Bad-Date Records],
    COUNT(GOOFYDATE) AS [Count of Just NON-NULL Bad-Date Records],
    SUM(IIF(GOOFYDATE IS NULL,1,0)) AS [Count of Just NULL Bad-Date Records]
FROM MyTable
WHERE ISDATE(GOOFYDATE)=0

以上所有加起来。

在 Informix 中,

SELECT COUNT(1)
FROM MyTable
WHERE DATE(GOOFYDATE) IS NULL

像以前一样给我总计。但是,以下内容也是如此:

SELECT COUNT(1)
FROM MyTable
WHERE DATE(GOOFYDATE) IS NULL
AND GOOFYDATE IS NULL

我如何在 Informix 中实现我在 SQL 服务器中实现的 ISDATE 目标?

您可以编写一个存储的 procedure/function 来执行此任务,这样它就可以像 SQL 服务器等价物一样工作。类似于:

CREATE FUNCTION informix.isdate(str VARCHAR(50), fmt VARCHAR(50))
    RETURNING SMALLINT;
    DEFINE d DATE;

    ON EXCEPTION IN (-1277,-1267,-1263) -- other errors are possible
        RETURN 0;
    END EXCEPTION;

    LET d = TO_DATE(str, fmt); -- acceptable date if exception not raised
    IF d < MDY(1,1,1850) THEN -- dates prior to this are "logically invalid"
        RETURN 0;
    END IF;
    RETURN 1;
END FUNCTION;

你可以这样使用:

-- Sample data
CREATE TEMP TABLE test1 (str VARCHAR(50));
INSERT INTO test1 VALUES ("not a date");
INSERT INTO test1 VALUES ("02/25/2016");
INSERT INTO test1 VALUES ("02/30/2016");
INSERT INTO test1 VALUES ("02/01/0000");

SELECT str, ISDATE(str, "%m/%d/%Y") FROM test1;

str                                                (expression)

not a date                                                    0
02/25/2016                                                    1
02/30/2016                                                    0
02/01/0000                                                    0

4 row(s) retrieved.

SELECT str AS invalid_date
  FROM test1
  WHERE ISDATE(str, "%m/%d/%Y") = 0;

invalid_date

not a date
02/30/2016
02/01/0000

3 row(s) retrieved.

根据您约会的愚蠢程度,您可能会发现其他错误。只需相应地调整 ON EXCEPTION 子句即可。我已将此函数编写为尽可能通用,但您可以将 "accepted" 日期格式编码到例程中,而不是将其作为参数传递。 (不过我不推荐这样做。)