错误日期:SQL 服务器提供 ISDATE(),但 Informix 不提供。是否有同等的解决方法?
Bad Dates: SQL Server Offers ISDATE(), But Informix Does Not. Is There an Equal Workaround?
我正在处理遗留的 Informix 数据,显然在输入时从未正确验证过。
这意味着 DATE 字段可以包含
- 一个合适的日期 (12/25/2000),
- 一个垃圾日期 (02/22/0200),
- NULL,或
- 林德伯格宝宝。
以下在 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" 日期格式编码到例程中,而不是将其作为参数传递。 (不过我不推荐这样做。)
我正在处理遗留的 Informix 数据,显然在输入时从未正确验证过。
这意味着 DATE 字段可以包含
- 一个合适的日期 (12/25/2000),
- 一个垃圾日期 (02/22/0200),
- NULL,或
- 林德伯格宝宝。
以下在 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" 日期格式编码到例程中,而不是将其作为参数传递。 (不过我不推荐这样做。)