WordPress PHP文件中含STR_TO_DATE的SQL查询返回空结果问题
WordPress $wpdb 查询返回空值的解决方法
先贴出你遇到问题的代码:
$query = $wpdb->prepare("SELECT post_id FROM {$wpdb->prefix}postmeta t1 WHERE meta_key = 'expiry_date' AND STR_TO_DATE(meta_value, '%Y-%m-%d') BETWEEN NOW() AND NOW() + INTERVAL 6 MONTH AND EXISTS (SELECT 1 FROM wp_postmeta t2 WHERE t2.meta_key = 'customer_email' AND t2.meta_value = %s AND t2.post_id = t1.post_id) GROUP BY post_id", 'test@hotmail.co.uk'); $result = $wpdb->get_results( $query, ARRAY_A );
执行这段代码时$result返回空值,问题出在日期转换的条件行:
AND STR_TO_DATE(meta_value, '%Y-%m-%d') BETWEEN NOW() AND NOW() + INTERVAL 6 MONTH
这段查询在phpMyAdmin能正常执行,但在WordPress的PHP文件里只有移除该行才能正常工作,核心原因是**$wpdb->prepare会将SQL语句中的%识别为参数占位符**,你写的%Y-%m-%d里的%会被prepare错误解析,导致最终生成的SQL中日期格式字符串被破坏,无法正确转换日期。
解决办法
把SQL中的%转义为%%,让$wpdb->prepare正确识别这是SQL语法的一部分而非参数占位符,同时可以优化日期匹配逻辑(用CURDATE()替代NOW(),避免时间部分干扰匹配):
$query = $wpdb->prepare("SELECT post_id FROM {$wpdb->prefix}postmeta t1 WHERE meta_key = 'expiry_date' AND STR_TO_DATE(meta_value, '%%Y-%%m-%%d') BETWEEN CURDATE() AND CURDATE() + INTERVAL 6 MONTH AND EXISTS (SELECT 1 FROM {$wpdb->prefix}postmeta t2 WHERE t2.meta_key = 'customer_email' AND t2.meta_value = %s AND t2.post_id = t1.post_id) GROUP BY post_id", 'test@hotmail.co.uk'); $result = $wpdb->get_results( $query, ARRAY_A );
补充说明
- 转义
%为%%是WordPress$wpdb->prepare的硬性要求,所有SQL语法中的%都需要这样处理,避免和参数占位符冲突。 - 用
CURDATE()替代NOW()是因为STR_TO_DATE转换后的结果是纯日期(无时间部分),NOW()包含时间会导致当天的日期无法被正确匹配(比如当前时间是2024-05-20 14:30,转换后的日期是2024-05-20 00:00,会小于NOW(),无法进入BETWEEN范围)。如果你的业务需要匹配带时间的日期字符串,可以调整为STR_TO_DATE(meta_value, '%%Y-%%m-%%d %%H:%%i:%%s'),并保持使用NOW()。
内容的提问来源于stack exchange,提问作者Ads
相关产品推荐
相关产品推荐

