PHP技术问询:如何查询并显示不在tempahanbilik表中的数据?
修正你的SQL查询逻辑与安全问题
嘿,我看你写的SQL逻辑完全搞反啦,咱们一步步来修正:
原代码的核心问题
- 表的查询方向错误:你想要的是
bilik表中未出现在符合日期条件的tempahanbilik记录里的数据,但原查询是从tempahanbilik表中筛选,这和你的需求完全颠倒了。 - 子查询逻辑错误:原子查询
SELECT bilik.id FROM bilik会取出所有房间ID,tempahanbilik.id NOT IN这个结果的话,相当于找tempahanbilik里不存在于bilik的无效ID,这显然不是你要的。 - 严重的SQL注入风险:直接把
$_SESSION里的变量拼接进SQL语句,恶意用户可以通过构造特殊值篡改你的查询,甚至破坏数据库。
正确的查询写法(两种常用方案)
方案1:使用NOT EXISTS(高效推荐)
这种方式在数据量大时性能更好,逻辑也清晰:
SELECT b.* FROM bilik b WHERE NOT EXISTS ( -- 检查当前bilik的ID是否在指定日期范围内的tempahanbilik中存在 SELECT 1 FROM tempahanbilik t WHERE t.id = b.id AND t.tarikh BETWEEN ? AND ? )
方案2:使用LEFT JOIN + IS NULL
另一种直观的写法,通过左连接后筛选无匹配的记录:
SELECT b.* FROM bilik b LEFT JOIN tempahanbilik t ON b.id = t.id AND t.tarikh BETWEEN ? AND ? -- 把日期条件放在连接条件里 WHERE t.id IS NULL -- 筛选出没有对应tempahanbilik记录的bilik
安全的PHP实现(用预处理语句避免注入)
一定要用mysqli的预处理语句来绑定参数,不要直接拼接变量:
// 准备预处理语句 $query = "SELECT b.* FROM bilik b WHERE NOT EXISTS ( SELECT 1 FROM tempahanbilik t WHERE t.id = b.id AND t.tarikh BETWEEN ? AND ? )"; // 初始化预处理 $stmt = $mysqli->prepare($query); if (!$stmt) { die("预处理失败: " . $mysqli->error); } // 绑定参数:'ss'表示两个字符串类型的参数(如果你的tarikh是日期类型,也可以用对应类型) $stmt->bind_param('ss', $_SESSION['tarikh'], $_SESSION['tarikh2']); // 执行查询 $stmt->execute(); // 获取结果集 $results = $stmt->get_result(); // 遍历输出数据 while ($row = $results->fetch_assoc()) { // 这里处理每条数据,比如echo $row['xxx']; } // 清理资源 $stmt->close();
内容的提问来源于stack exchange,提问作者Hasifah Hassan
相关产品推荐
相关产品推荐

