2016-06-13 18 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格式模式相匹配,这将是有点简单。

相关问题