0

我有一个查询,我需要将 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

提前致谢

4

2 回答 2

0

在这种情况下,我永远无法完全让正则表达式正常工作——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。

祝你好运。

于 2013-02-05T05:29:14.047 回答
0

以下正则表达式验证日期:

^(((?=\d{2}\.(0[13578]|1[02]))(0[1-9]|[12]\d|3[01]))|((?=\d{2}\.(0[469]|11))(0[1-9]|[12]\d|30))|((?=\d{2}\.02\.\d{2}([02468][048]|[13579][26]))(0[1-9]|[12]\d))|(((?=\d{2}\.02\.\d{2}([02468][^048]|[13579][^26]))(0[1-9]|1\d|2[0-8]))))\.(0[1-9]|1[0-2])\.(0{3}[1-9]|((?!0{3}\d)\d{4}))$

注意:将有一个使用条件表达式的更简单的正则表达式。

于 2013-02-05T05:15:36.207 回答