PHP通过GET获取日期进行SQL范围查询时结束日期数据未显示的问题求助
问题分析与解决方案
咱们来拆解下你遇到的问题:查询没返回17/10/2021的记录,核心原因是日期格式的字符串比较和数据库日期类型的逻辑不匹配,另外你的代码还存在严重的SQL注入风险,得一起解决。
为什么17号的记录查不到?
你传递的日期是DD/MM/YYYY格式(比如14/10/2021),如果你的lvlCol_dateTime字段是DATETIME/DATE类型,MySQL默认只识别YYYY-MM-DD格式的日期字符串。当你传入14/10/2021时,MySQL无法正确解析,会把它当成无效日期(比如0000-00-00),导致BETWEEN条件完全没按预期的日期范围过滤。
就算字段是字符串类型,若记录里包含时分秒(比如17/10/2021 14:30:00),作为字符串它会比纯日期的17/10/2021大,自然不会被包含在BETWEEN范围内。
正确的解决步骤
1. 转换日期为数据库可识别的标准格式
先用PHP把DD/MM/YYYY转成YYYY-MM-DD HH:MM:SS格式,确保数据库能按日期逻辑处理:
// 处理起始日期,设置为当天0点 $fromDateStr = $_GET['fromDate']; $fromDate = DateTime::createFromFormat('d/m/Y', $fromDateStr); $formattedFrom = $fromDate->format('Y-m-d 00:00:00'); // 处理结束日期,设置为当天23:59:59,确保包含全天记录 $toDateStr = $_GET['todate']; $toDate = DateTime::createFromFormat('d/m/Y', $toDateStr); $formattedTo = $toDate->format('Y-m-d 23:59:59');
2. 用预处理语句避免SQL注入(必须做!)
直接把$_GET变量拼进SQL是高危操作,极易被SQL注入攻击。用PDO预处理绑定参数才是安全规范的做法:
// 准备带占位符的SQL语句 $sql = "SELECT lvlCol_amt, lvlCol_type, lvlCol_directEarn_perct, lvlCol_directEarn_amt, lvlCol_associateId, lvlCol_collectId, lvlCol_dateTime FROM `t_lvl_collect` WHERE lvlCol_dateTime BETWEEN :fromDate AND :toDate AND lvlCol_associateId = :memberId ORDER BY lvlCol_dateTime DESC"; // 预处理SQL $stmt = $conn->prepare($sql); // 绑定参数,指定类型更严谨 $stmt->bindParam(':fromDate', $formattedFrom, PDO::PARAM_STR); $stmt->bindParam(':toDate', $formattedTo, PDO::PARAM_STR); $stmt->bindParam(':memberId', $MemberId, PDO::PARAM_INT); // 执行查询 $stmt->execute(); // 获取结果集 $collect_Amt = $stmt->fetchAll(PDO::FETCH_ASSOC);
3. 额外的日期有效性验证
为了防止用户传入无效日期,建议在转换前做校验:
if (!$fromDate || !$toDate) { die("日期格式错误!请使用DD/MM/YYYY格式。"); }
为什么这样能解决问题?
- 转换后的日期格式是数据库能正确识别的,
BETWEEN条件会按日期逻辑比较,17号全天的记录(包括到23:59:59的)都会被包含进来。 - 预处理语句把变量和SQL逻辑彻底分离,从根源上杜绝了SQL注入风险,这是生产环境代码必须遵守的规范。
内容的提问来源于stack exchange,提问作者Surendra Kumar
相关产品推荐
相关产品推荐

