2016-06-13 49 views
-1

我有過提示 一些東西輸入多個日期的問題我的查詢像甲骨文非數字字符被發現,其中一個數字預計

select something 
from 
something 
where 
to_date (bus.TDATE) not in (:didb1) 

我要像'12 -Jun-2016輸入」,'11 -Jun-2016'

我做PHP的Oracle, 我的代碼如下:

select bus.*,con.* from 
BusinessPayment bus, 
ConsumerPayment con 
where bus.TDATE=con.TDATE 
and to_date (bus.TDATE) not in (:didbv) 
'); 
$bscode1='11-June-2016','10-June-2016','09-June-2016'; 
oci_bind_by_name($stid, ':didbv', $bscode1); 
oci_execute($stid); 
+0

請檢查這[URL](http://stackoverflow.com/help)這將有助於提高您的質量 –

+0

可能重複的[獲取錯誤 - ORA-01858:一個非數字字符被發現的地方數字是預期的](http://stackoverflow.com/questions/29852389/getting-error-ora-01858-a-non-numeric-character-was-found-where-a-numeric-was) –

回答

0

不能使用單一的綁定變量represe nt in()子句中的值列表。綁定變量不包含多個值;您綁定的值被視爲單個字符串值。所以你切實做好:

where 
to_date (bus.TDATE) not in (q'['11-June-2016','10-June-2016','09-June-2016']') 

如果TDATE已經是一個日期類型 - 它希望是,與加入暗示它可能是 - 那麼你不應該通過,通過to_date() - 你正在做一個隱式從日期轉換爲字符串,然後使用會話的NLS_DATE_FORMAT將半顯式轉換回日期。這要麼做不必要的工作,要麼失去分辨率,這取決於你的格式模型以及日期是否有時間。如果意圖是忽略價值的時間部分,那麼有更好的方法來做到這一點。

無論如何,因爲這是現在一個日期無論何種類型是前,右有這樣的過濾器的側面也將轉換爲日期,所以你在做:

where 
to_date (bus.TDATE) not in (to_date(q'['11-June-2016','10-June-2016','09-June-2016']')) 

...和正是拋出異常,無論你的NLS設置是什麼。即使您傳遞了單個值,由於嵌入的單引號也會導致錯誤。您可以複製與:

select to_date(q'['11-June-2016','10-June-2016','09-June-2016']') from dual; 

這也得到ORA-01858:一個非數字字符被發現,其中一個數字預期。

理想情況下,您可以將各個日期字符串作爲數組元素傳遞,但您也可以使用XML hack解決此問題。你可以傳遞一個字符串包含逗號分隔值XMLTable(),它會在把它分解到行:

select * from xmltable(q'['11-June-2016','10-June-2016','09-June-2016']'); 

COLUMN_VALUE                 
-------------------------------------------------------------------------------- 
11-June-2016 
10-June-2016 
09-June-2016 

然後,你可以對這些值轉換爲日期:

select to_date(column_value, 'DD-Month-YYYY') 
from xmltable(q'['11-June-2016','10-June-2016','09-June-2016']') 

和使用在子查詢或連接:

select * from dual 
where trunc(sysdate) not in (select to_date(column_value, 'DD-Month-YYYY') 
    from xmltable(q'['11-June-2016','10-June-2016','09-June-2016']')); 

那與字符串綁定變量的作品,所以你的代碼將是:

select bus.*,con.* 
from BusinessPayment bus 
join ConsumerPayment con 
on bus.TDATE=con.TDATE 
where bus.TDATE not in (select to_date(column_value, 'DD-Month-YYYY') 
     from xmltable(:didbv)); 

我已經修改了這個以使用ANSI連接語法,這是不相關的,但很少有使用古代語法的原因。如果TDATE確實包含了需要修改的時間 - 截斷最簡單但可能會影響性能。

或者你可以加入:

select bus.*,con.* 
from xmltable(:didbv) x 
join BusinessPayment bus 
on bus.TDATE >= to_date(x.column_value, 'DD-Month-YYYY') 
and bus.TDATE < to_date(x.column_value, 'DD-Month-YYYY') + 1 
join ConsumerPayment con 
on bus.TDATE=con.TDATE 

在這個版本中TDATE可以有一個時間,並在綁定變量指定天內的任何時間相匹配。

如果以不包含月份名稱的格式提供日期會更好,因爲這會在不同會話或區域設置中運行時出現問題。如果你知道PHP端將永遠是英語,你可以強制要識別:

on bus.TDATE >= to_date(x.column_value, 'DD-Month-YYYY', #NLS_DATE_LANGUAGE=ENGLISH') 

,但如果你可以改變PHP格式使用月數,並更改Oracle格式模式相匹配,這將是有點簡單。

相關問題