3

このクエリは実行され、行は返されません。

SELECT DISTINCT TO_CHAR(START_DATE,'MM/DD/YYYY'),                             
                TO_CHAR(END_DATE,  'MM/DD/YYYY')                              
FROM                                                                          
(                                   
    SELECT START_DATE, END_DATE, END_DATE - START_DATE
    FROM
    (
        SELECT TO_DATE(SUBSTR(B,  1, 10), 'MM/DD/YYYY') START_DATE,               
               TO_DATE(SUBSTR(B, 14, 10), 'MM/DD/YYYY') END_DATE                  
        FROM (SELECT 'test date' b from dual)
    )
    WHERE END_DATE - START_DATE != 6
)

変換エラーのため、この小さな断片は実行に失敗します。 [1]: ORA-01858: 数値が必要な場所に数値以外の文字が見つかりました

SELECT TO_DATE(SUBSTR(B,  1, 10), 'MM/DD/YYYY') START_DATE,               
       TO_DATE(SUBSTR(B, 14, 10), 'MM/DD/YYYY') END_DATE                  
FROM (SELECT 'test date' b from dual)

ここでの私の予想は、変換エラーによって Oracle 例外が発生し、プログラムが失敗することでした。わからないことや、正しく考えていないことがあります。

誰かがこれで私の鼻を正しい方向に向けることができますか?

ありがとう。悪の。

編集 - NULL は to_date とは異なる方法で処理されます。 Oracle: to_date で NULL 値を回避する

編集 - 計画

3 SELECT STATEMENT  ALL_ROWS
Cost: 3  Bytes: 0  Cardinality: 1  
Partition #: 0          
    2 FILTER  
    Cost: 0  Bytes: 0  Cardinality: 0  
    Partition #: 0      
        1 FAST DUAL  
        Cost: 2  Bytes: 0  Cardinality: 1  
        Partition #: 0 

編集 - 私は10gを実行しています。

4

1 に答える 1

5

OK、私はそれが私を夢中にさせていたので、これを理解しました. クエリを単純化すると、次のようになります。

SELECT START_DATE, END_DATE, END_DATE - START_DATE
FROM
(
    SELECT TO_DATE(SUBSTR(B,  1, 10), 'MM/DD/YYYY') START_DATE,               
           TO_DATE(SUBSTR(B, 14, 10), 'MM/DD/YYYY') END_DATE                  
    FROM (SELECT 'test date' b from dual)
)
WHERE END_DATE - START_DATE != 6

結果の実行計画 (11gR2) は次のようになります。

Execution Plan
----------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|*  1 |  FILTER          |      |       |            |          |
|   2 |   FAST DUAL      |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(TO_DATE(NULL)-TO_DATE('test date','MM/DD/YYYY')<>6)

そのため、CBO は END_DATE の部分文字列が null であると判断したため、to_date も null 値になります。その後、オプティマイザーは START_DATE 式を評価しないため、無効なデータ形式エラーは発生しません。以下を実行すると、同じ動作を確認できます。

SELECT TO_DATE (NULL) - TO_DATE ('test date', 'MM/DD/YYYY') FROM DUAL

失敗しません。

于 2014-04-02T20:24:27.270 に答える