我有问题,通过提示输入多个日期 我的查询类似
select something
from
something
where
to_date (bus.TDATE) not in (:didb1)
我想输入类似于2016年6月12日',' 2016年6月11日'
我正在做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 :(得分:0)
您不能使用单个绑定变量来表示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格式模型以匹配,那将会更简单。