日期检查以避免sql中的异常

时间:2013-02-05 04:47:36

标签: sql regex oracle

我有一个查询,我需要将TO_DATE(指定格式为'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& amp ;;执行了所有验证。案件而且相当冗长。


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

提前致谢

2 个答案:

答案 0 :(得分: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}))$

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

答案 1 :(得分: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。

祝你好运。