为含三层SELECT的SQL查询添加table_shots表的teamtype约束
给SQL预处理语句添加teamtype字段约束的解决方案
嘿,我来帮你搞定这个需求。首先得提一句:你原来的语句直接把$idTeam和$num拼进SQL里,这可是SQL注入的高危操作,完全浪费了预处理的安全优势,得先把这个问题修正。再来说怎么关联比赛信息,精准筛选teamtype字段。
核心思路
我们需要先从table_matches里拿到目标球队参与的最近$num场比赛,同时明确该球队在每场比赛里是主场还是客场;再把这个球队类型信息和table_shots关联,只保留对应teamtype的射门记录。
优化后的预处理代码
// 准备带参数占位符的SQL语句,用JOIN关联两张表 $stmt = $conn->prepare(' SELECT s.* FROM table_shots s INNER JOIN ( SELECT mc_id, -- 标记当前球队在这场比赛中的类型(主场/客场) CASE WHEN mc_hometeam = ? THEN "home_team" WHEN mc_awayteam = ? THEN "away_team" END AS target_team_type FROM table_matches WHERE mc_hometeam = ? OR mc_awayteam = ? ORDER BY mc_date DESC LIMIT ? ) m ON s.idmatch = m.mc_id -- 匹配射门记录的teamtype和比赛中的球队类型 WHERE s.teamtype = m.target_team_type '); // 绑定参数:参数顺序要和SQL里的?一一对应 // 这里的"iiii"表示5个整数类型参数,如果你的ID是字符串就换成"sssss" $stmt->bind_param('iiii', $idTeam, $idTeam, $idTeam, $idTeam, $num); // 执行查询 $stmt->execute();
写法说明
- 解决SQL注入风险:所有动态变量都用
?占位符,通过bind_param绑定,彻底避免了直接拼接字符串的安全漏洞; - 精准关联球队类型:子查询里用
CASE语句判断目标球队是主场还是客场,生成target_team_type,再和射门表的teamtype匹配,确保只查询该球队在对应比赛中的射门记录; - 逻辑更清晰:把原来的三层嵌套子查询改成了JOIN结构,可读性和查询性能都更优。
简化版(减少参数重复)
如果觉得重复写?有点繁琐,也可以用IF函数简化子查询的判断逻辑,这样能少一个参数:
$stmt = $conn->prepare(' SELECT s.* FROM table_shots s INNER JOIN ( SELECT mc_id, IF(mc_hometeam = ?, "home_team", "away_team") AS target_team_type FROM table_matches WHERE mc_hometeam = ? OR mc_awayteam = ? ORDER BY mc_date DESC LIMIT ? ) m ON s.idmatch = m.mc_id WHERE s.teamtype = m.target_team_type '); // 绑定参数:顺序对应SQL里的? $stmt->bind_param('iii', $idTeam, $idTeam, $idTeam, $num); $stmt->execute();
内容的提问来源于stack exchange,提问作者user9324524
相关产品推荐
相关产品推荐

