日期检查以避免 sql 中的异常
Posted
技术标签:
【中文标题】日期检查以避免 sql 中的异常【英文标题】:date check to avoid exception in sql 【发布时间】:2013-02-05 04:47:35 【问题描述】:我有一个查询,我需要将 TO_DATE(format specified is 'DD.MM.YYYY') 函数应用于 VARCHAR 类型列。但是,日期可能无效 例如'aa.12.2012' 或 '31.02.2012' 等
这将导致TO_DATE函数处理错误日期值时出现异常,查询将失败。
一种方法是运行光标并识别每个日期错误的单元格,但我想避免这种方式。
我尝试使用正则表达式,但我没有成功放置所有验证。
原来是这样
select
case
when regexp_like('24.01.2013',
'[[:digit:]]2.[[:digit:]]2.[[:digit:]]4') then
1
else
0
end chk
from dual
这无法捕获像 2 月 31 日这样的无效日期。
是否可以在正则表达式中对日期进行所有验证,因为我通过 decode & case 执行了所有验证,而且相当冗长。
SELECT DECODE((REPLACE(TRANSLATE('29.01.2013', '0123456789.', ' '), ' ', '')),
NULL,
(CASE
WHEN LENGTH('29.01.2013') != 10 THEN
'FALSE'
WHEN LENGTH('29.01.2013') -
LENGTH(REPLACE(TRANSLATE('29.01.2013', '.', ' '),
' ',
'')) != 2 THEN
'FALSE'
WHEN INSTR('29.01.2013', '.', 1, 1) != 3 THEN
'FALSE'
WHEN INSTR('29.01.2013', '.', 1, 2) != 6 THEN
'FALSE'
WHEN TO_NUMBER(SUBSTR('29.01.2013', 4, 2)) IN
(1, 3, 5, 7, 8, 10, 12) THEN
(CASE
WHEN TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) >= 1 AND
TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) <= 31 THEN
'TRUE'
ELSE
'FALSE'
END) WHEN
TO_NUMBER(SUBSTR('29.01.2013', 4, 2)) IN (4, 6, 9, 11)
THEN(CASE
WHEN TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) >= 1 AND
TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) <= 30 THEN
'TRUE'
ELSE
'FALSE'
END) WHEN TO_NUMBER(SUBSTR('29.01.2013', 4, 2)) IN (2)
THEN(CASE
WHEN REMAINDER(TO_NUMBER(SUBSTR('29.01.2013', 7, 4)), 4) = 0 THEN
(CASE
WHEN TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) >= 1 AND
TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) <= 29 THEN
'TRUE'
ELSE
'FALSE'
END) WHEN
REMAINDER(TO_NUMBER(SUBSTR('29.01.2013', 7, 4)), 4) != 0
THEN(CASE
WHEN TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) >= 1 AND
TO_NUMBER(SUBSTR('29.01.2013', 1, 2)) <= 28 THEN
'TRUE'
ELSE
'FALSE'
END) END) END), 'FALSE')
FROM DUAL
提前致谢
【问题讨论】:
为什么首先将DATE
存储在VARCHAR
列中。如果你使用正确的数据类型,那么你就不需要这样的杂牌
公平点,但是我将 excel 中的值(不检查)转储到该字段中。如果出现日期格式错误,我需要准确识别和报告,否则将使用有效日期
【参考方案1】:
以下正则表达式验证日期:
^(((?=\d2\.(0[13578]|1[02]))(0[1-9]|[12]\d|3[01]))|((?=\d2\.(0[469]|11))(0[1-9]|[12]\d|30))|((?=\d2\.02\.\d2([02468][048]|[13579][26]))(0[1-9]|[12]\d))|(((?=\d2\.02\.\d2([02468][^048]|[13579][^26]))(0[1-9]|1\d|2[0-8]))))\.(0[1-9]|1[0-2])\.(03[1-9]|((?!03\d)\d4))$
注意:会有一个使用条件表达式的更简单的正则表达式。
【讨论】:
【参考方案2】:在这种情况下,我永远无法让正则表达式完全正常工作——99% 的情况下都可以,但像闰年这样的事情总是很困难。
我之前在网上看到过这个似乎效果很好:
CREATE OR REPLACE FUNCTION MY2DATE (p_str IN VARCHAR2
,format_picture IN VARCHAR2
)
RETURN DATE
IS
BEGIN
RETURN TO_DATE(p_str, format_picture);
EXCEPTION
WHEN OTHERS
THEN
RETURN NULL;
END;
/
基本上,传递字符串值和格式,如果捕获到任何异常,它将返回 NULL。
祝你好运。
【讨论】:
我已经这样做了,但我希望这需要一个程序。我想编写一个避免无效日期的查询。像 IS NULL 这样的东西,它成功地避免了 NULL 值行。我只想避免无效日期以上是关于日期检查以避免 sql 中的异常的主要内容,如果未能解决你的问题,请参考以下文章
在java中,String转换Date日期类型容易出现时间转换异常,如何避免!
如何检查数组元素是不是为空以避免Java中的NullPointerException