Laravel对接Oracle按日期筛选记录报ORA-01841错误
问题根因
Laravel的Eloquent默认where方法会将第二个参数作为PDO绑定参数处理,不会解析参数里的SQL函数。你写的to_date('22/06/2022' , 'DD/MM/YYYY')会被整体当成字符串值绑定到SQL语句中,Oracle拿到这个字符串后会尝试隐式转换为日期类型,无法解析出合法年份,最终触发ORA-01841错误。
该语句在Oracle SQL Developer中能正常执行,是因为直接执行原生SQL时to_date函数会被SQL引擎正常解析执行,不存在参数绑定把函数整体当字符串字面量的问题。
可行解决方案
以下三种方案都可以解决问题,按推荐优先级排序:
- 使用
whereRaw方法配合参数绑定,既保留SQL注入防护能力,又能让Oracle正确识别日期函数
$records = Record::whereRaw( 'INVH_DT = to_date(?, \'DD/MM/YYYY\')', ['22/06/2022'] )->get();
- 先将目标日期转为PHP的
DateTime实例,再传入查询条件,Laravel的Oracle驱动(常用的如yajra/laravel-oci8)会自动完成日期格式适配,不需要手动写to_date函数
$targetDate = DateTime::createFromFormat('d/m/Y', '22/06/2022'); $records = Record::where('INVH_DT', $targetDate)->get();
- 如果查询的日期是固定硬编码值、不存在用户可控输入,也可以直接写完整原生条件(日期值来自用户输入时禁止用该写法,存在SQL注入风险)
$records = Record::whereRaw( "INVH_DT = to_date('22/06/2022', 'DD/MM/YYYY')" )->get();
注意:不要尝试更换
to_date内的日期格式来修复问题,只要你把to_date(...)整体作为where方法的第二个参数,Laravel就会始终把它当普通字符串绑定,不管格式怎么改都会触发隐式转换错误。
内容的提问来源于stack exchange,提问作者Albaraa Alshahhoud
相关产品推荐
相关产品推荐

