Laravel Tinker执行SQL Server查询报日期时间字符串转换失败
问题产生原因
- 核心错误是对Laravel查询构造器的参数绑定逻辑理解有误:你直接将
convert()函数拼接在where条件的第三个参数中,查询构造器会将整个字符串作为普通绑定值处理,不会将其解析为SQL原生函数;同时拼接进去的日期值2022-06-21没有包裹单引号,SQL Server会将其识别为算术表达式(2022减6减21,计算结果为整数1995),根本不是合法的日期字符串,无论调整convert的格式参数(121/102/105)都无法解决转换错误。 - 你在DataGrip中能正常运行,是因为手写原生SQL时日期值加了单引号、convert函数直接写在SQL语句结构中,不存在参数绑定把函数当字符串处理的问题。
- 额外隐患:你当前生成的SQL中
like后的匹配字符串也没有自动生成单引号,就算日期问题修复,这部分也会触发语法错误,只是被前序报错覆盖了。 - 小问题:代码中
Unidade_lan传入的0001带前导零,PHP中直接写带前导零的数字会被解析为八进制数值,可能和字段实际存储值不匹配。
修复方案
你可以选以下任意一种方式修改,推荐优先用更简洁的第二种:
方案1:用whereRaw写原生日期条件
使用whereRaw方法编写需要原生SQL函数的部分,通过占位符绑定参数,既可以正确识别convert函数,也能避免SQL注入风险:
$bol_vencimento = '2022-06-21'; $count = BoletoPropCondominio::where('Unidade_lan', 1) ->where('Id_Condo_lan', 77) ->whereNull('Data_pagamento') ->whereRaw('Bol_vencimento > convert(datetime, ?, 121)', [$bol_vencimento]) ->where(function($query) { $query->where('Especifica_boleto', 'like', '%ACORDO JUDICIAL%') ->orWhere('Especifica_boleto', 'like', '%ACORDO EXTRAJUDICIAL%'); }) ->count();
方案2:直接传日期值,让Laravel自动处理类型适配
不需要手动写SQL Server的convert函数,只要传入合法的日期字符串或者Carbon日期实例,Laravel的SQL Server驱动会自动完成日期类型的适配转换,代码更简洁可维护:
$bol_vencimento = '2022-06-21'; // 也可以传入Carbon实例:$bol_vencimento = \Carbon\Carbon::parse('2022-06-21'); $count = BoletoPropCondominio::where('Unidade_lan', 1) ->where('Id_Condo_lan', 77) ->whereNull('Data_pagamento') ->where('Bol_vencimento', '>', $bol_vencimento) ->where(function($query) { $query->where('Especifica_boleto', 'like', '%ACORDO JUDICIAL%') ->orWhere('Especifica_boleto', 'like', '%ACORDO EXTRAJUDICIAL%'); }) ->count();
内容的提问来源于stack exchange,提问作者GabrielTura
相关产品推荐
相关产品推荐

