从两个MySQL表查询用户名的SQL语句问题求助
问题分析与解决方案
你的核心问题出在SQL语句的语法错误,还有对UNION用法的误解。先看你原来的SQL:
$sql = "SELECT * FROM tableA OR SELECT * from tableB ORDER BY added" . $queryCondition;
这完全不符合MySQL的语法规范,OR不能用来连接两个独立的SELECT语句,而且WHERE条件的位置也完全错了,这就是为什么联合查询没有结果的原因。下面一步步给你解决:
1. 正确使用UNION ALL连接两个表
要从两个表获取数据,必须用UNION或UNION ALL(推荐用UNION ALL,因为不会去重,性能更好),但有个前提:两个查询返回的结果集必须列数相同,且对应列的数据类型兼容。
不要直接用SELECT *,除非你能保证两个表的列顺序和类型完全一致,否则会报错或者返回异常结果。建议明确指定要查询的列,比如:
SELECT username, code, added, link, image, usertype, regdate FROM tableA UNION ALL SELECT username, code, added, link, image, usertype, regdate FROM tableB
2. 正确添加查询条件
你的查询条件需要分别应用到两个表上,因为是要过滤每个表中的数据,再合并结果。首先调整条件构建逻辑,去掉WHERE关键字,只保留条件内容:
$queryCondition = ""; if(!empty($_POST["search"])) { foreach($_POST["search"] as $k=>$v){ if(!empty($v)) { $queryCases = array("username","code"); if(in_array($k,$queryCases)) { if(!empty($queryCondition)) { $queryCondition .= " AND "; } } switch($k) { case "username": $username = $v; $queryCondition .= "username LIKE '%" . $v . "%'"; break; case "code": $code = $v; $queryCondition .= "code LIKE '%" . $v . "%'"; break; } } } }
然后构建SQL时,给每个SELECT单独加上条件:
// 基础查询部分,明确指定列 $selectColumns = "username, code, added, link, image, usertype, regdate"; $sqlA = "SELECT " . $selectColumns . " FROM tableA"; $sqlB = "SELECT " . $selectColumns . " FROM tableB"; // 如果有查询条件,分别加到两个表的查询后 if(!empty($queryCondition)) { $sqlA .= " WHERE " . $queryCondition; $sqlB .= " WHERE " . $queryCondition; } // 用UNION ALL合并,然后整体排序 $sql = $sqlA . " UNION ALL " . $sqlB . " ORDER BY added DESC";
3. 修正分页逻辑
原来的分页拼接有重复排序的问题,要确保LIMIT加在整个联合查询的最后,排序要在LIMIT之前:
$orderby = ""; // 已经在$sql里定义了排序,这里不需要重复 $query = $sql . " limit " . $start . "," . $perPage;
4. 重要安全提示:防止SQL注入
你的代码现在有严重的SQL注入风险!直接把用户输入拼接到SQL里非常危险,一定要对用户输入进行转义处理,比如:
// 假设$db_handle是mysqli连接对象,转义用户输入 $v = $db_handle->real_escape_string($v); $queryCondition .= "username LIKE '%" . $v . "%'";
更稳妥的方式是使用预处理语句+参数绑定,彻底避免注入风险。
修改后的完整核心代码
$username = ""; $code = ""; $queryCondition = ""; if(!empty($_POST["search"])) { foreach($_POST["search"] as $k=>$v){ if(!empty($v)) { // 转义用户输入,防止SQL注入 $v = $db_handle->real_escape_string($v); $queryCases = array("username","code"); if(in_array($k,$queryCases)) { if(!empty($queryCondition)) { $queryCondition .= " AND "; } } switch($k) { case "username": $username = $v; $queryCondition .= "username LIKE '%" . $v . "%'"; break; case "code": $code = $v; $queryCondition .= "code LIKE '%" . $v . "%'"; break; } } } } // 构建两个表的查询语句,明确指定列 $selectColumns = "username, code, added, link, image, usertype, regdate"; $sqlA = "SELECT " . $selectColumns . " FROM tableA"; $sqlB = "SELECT " . $selectColumns . " FROM tableB"; // 添加查询条件 if(!empty($queryCondition)) { $sqlA .= " WHERE " . $queryCondition; $sqlB .= " WHERE " . $queryCondition; } // 合并查询并排序 $sql = $sqlA . " UNION ALL " . $sqlB . " ORDER BY added DESC"; $href = 'abcd.php'; $perPage = 5; $page = 1; if(isset($_POST['page'])){ $page = $_POST['page']; } $start = ($page-1)*$perPage; if($start < 0) $start = 0; // 拼接分页 $query = $sql . " limit " . $start . "," . $perPage; $result = $db_handle->runQuery($query); if(!empty($result)) { $result["perpage"] = showperpage($sql, $perPage, $href); }
额外检查点
- 确认
tableA和tableB都包含你查询的所有列:username, code, added, link, image, usertype, regdate - 如果两个表的列名不一致,需要用别名统一,比如
SELECT user_name AS username FROM tableA - 可以先把生成的SQL语句复制到MySQL客户端中运行,看是否能返回结果,这样更容易排查问题
内容的提问来源于stack exchange,提问作者SALIM MURSHED
相关产品推荐
相关产品推荐

