0

TO_DATE(指定された形式は 'DD.MM.YYYY') 関数を VARCHAR 型の列に適用する必要があるクエリがあります。ただし、「aa.12.2012」や「31.02.2012」など、日付が無効である可能性があります。

これにより、TO_DATE 関数が誤った日付値を処理するときに例外が発生し、クエリが失敗します。

それを行う1つの方法は、カーソルを実行して、日付が間違っているすべてのセルを特定することですが、この方法は避けたいです。

正規表現で作業しようとしましたが、すべての検証を配置することに成功しませんでした.

こんな感じでした


select
 case
   when regexp_like('24.01.2013',
                    '[[:digit:]]{2}.[[:digit:]]{2}.[[:digit:]]{4}') then
    1
   else
    0
 end chk
  from dual

これは、2 月 31 日のような無効な日付をキャッチできませんでした。

デコードとケースを介してすべての検証を実行しましたが、かなり時間がかかるため、日付の正規表現ですべての検証を行うことは可能ですか?


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 に答える