2016-06-16 7 views
0

誰かがこのケースを説明できますか? 例、私はこのようなデータをダンプテーブルを持っている:SQL Oracleでは、差異の結果INとBETWEEN

私はこのクエリを実行
TGL 
19810909 
19761026 
19832529 

SELECT to_date(tgl,'YYYYMMDD') tgl 
    FROM 
     (
     SELECT tgl 
     FROM tmpx 
     WHERE 
     SUBSTR(tgl,5,2) BETWEEN '01' AND '12' 
     AND length(tgl) = 8 
     ) 
    WHERE to_date(tgl,'YYYYMMDD') < to_date('19811231','YYYYMMDD') 

結果:エラーなし

TGL 
09/09/1981 
26/10/1976 

しかし、私は実行このクエリでは:

SELECT to_date(tgl,'YYYYMMDD') tgl 
FROM 
    (
    SELECT tgl 
    FROM tmpx 
    WHERE 
    SUBSTR(tgl,5,2) IN ('01','02','03','04','05','06','07','08','09','10','01','12') 
    AND length(tgl) = 8 
    ) 
WHERE to_date(tgl,'YYYYMMDD') < to_date('19811231','YYYYMMDD') 

結果:エラー

ORA-01843: not a valid month 

理由行番号第(19832529)は、エラーが発生し、選択に含めますか? 一方、私は次のクエリを実行場合:

SELECT tgl 
FROM tmpx 
WHERE 
SUBSTR(tgl,5,2) IN ('01','02','03','04','05','06','07','08','09','10','11','12') 
AND length(tgl) = 8 

結果は(行番号3 wihtout)このようなものです

TGL 
19810909 
19761026 

はあなたに感謝を。

答えて

1

両方のクエリの実行計画を見ると、それらがオプティマイザによってどのように処理されているかを見ることができます。最初のものの場合:

--------------------------------------------------------------------------            
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  |            
--------------------------------------------------------------------------            
| 0 | SELECT STATEMENT |  |  1 |  6 |  3 (0)| 00:00:01 |            
|* 1 | TABLE ACCESS FULL| TMPX |  1 |  6 |  3 (0)| 00:00:01 |            
--------------------------------------------------------------------------            

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

    1 - filter(LENGTH("TGL")=8 AND SUBSTR("TGL",5,2)>='01' AND               
       SUBSTR("TGL",5,2)<='12' AND TO_DATE("TGL",'YYYYMMDD')<TO_DATE('           
       1981-12-31 00:00:00', 'syyyy-mm-dd hh24:mi:ss')) 

そして第二のために:

--------------------------------------------------------------------------            
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  |            
--------------------------------------------------------------------------            
| 0 | SELECT STATEMENT |  |  1 |  6 |  3 (0)| 00:00:01 |            
|* 1 | TABLE ACCESS FULL| TMPX |  1 |  6 |  3 (0)| 00:00:01 |            
--------------------------------------------------------------------------            

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

    1 - filter(LENGTH("TGL")=8 AND TO_DATE("TGL",'YYYYMMDD')<TO_DATE('             
       1981-12-31 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND              
       (SUBSTR("TGL",5,2)='01' OR SUBSTR("TGL",5,2)='02' OR              
       SUBSTR("TGL",5,2)='03' OR SUBSTR("TGL",5,2)='04' OR              
       SUBSTR("TGL",5,2)='05' OR SUBSTR("TGL",5,2)='06' OR              
       SUBSTR("TGL",5,2)='07' OR SUBSTR("TGL",5,2)='08' OR              
       SUBSTR("TGL",5,2)='09' OR SUBSTR("TGL",5,2)='10' OR              
       SUBSTR("TGL",5,2)='12'))   

は、フィルタが適用される順序に注意してください。最初のものでは、最初に部分文字列を調べて、そのフィルタを渡す値だけを1998年の比較の日付に変換します。

第2のものでは、日付チェックが最初に実行されているため、無効な値をフィルタ処理する前に変換しようとします。

実際の問題は、無効なデータを入力できるように日付を文字列として保存することです。もしあなたがそれに固執しているのであれば、関数を使って文字列を日付に変換し、投げられたエラーを無視しようとします。これはまだ理想的ではありませんが、あなたがすでに持っているのと同じ値を無視します。この例の多くは、including this one of mineです。

SELECT safe_to_date(tgl) tgl 
FROM tmpx 
WHERE safe_to_date(tgl) < date '1981-12-31'; 

をまたはあなたが好む場合:そのような何かを使用すると、何ができる

SELECT tgl 
FROM (
    SELECT safe_to_date(tgl) tgl 
    FROM tmpx 
) 
WHERE tgl < date '1981-12-31'; 

のみYYYYMMDD形式の文字列を見ることができる、またはあなたがあれば、チェックしたい形式で渡すことができますあなたの機能あなたはそれが柔軟であることを望んでいません。

+0

fyi、ダンプテーブルのデータはインポートtxtファイルからのものです。 (where toddate(tgl、 'YYYYMMDD') thesuhu

+0

サブクエリは、最初に結果2行を取得する必要があります – thesuhu

+0

@thesuhu - しかし、それは決定する最適化するまでです。 SQL \ * Loaderまたは外部テーブル定義から 'safe_to_date()'型関数を呼び出すことができます。あるいは、オプティマイザが別の方法で選択した場合、1日で中断する可能性のある 'between'バージョンを使用してください。しかし、実際に、そのフィールドに無効なデータがある場合、他のデータが正しいか間違っているのかは分かりませんが、検証が行われます。 –

関連する問題