MySQL插入/更新前校验问题:代码无法运行,求排查原因
你的MySQL插入/更新代码问题分析与修复
首先,咱们先搞定导致代码无法运行的直接语法错误:
- 看你的INSERT语句:
VALUES ('".$details['name']."', '".$details['idu'].")"—— 这里拼接idu值的时候,少了一个闭合的单引号,还多了个多余的右括号,应该改成VALUES ('".$details['name']."', '".$details['idu']."') - 再看UPDATE语句:
SET idu='".$details['idu'].") WHERE name='"—— 同样的问题,少了闭合单引号,还多了右括号,正确写法是SET idu='".$details['idu']."' WHERE name='"
不过,就算你修复了这些语法问题,你的代码还有两个大问题:
- SQL注入风险极高:直接把
$details里的内容拼接到SQL语句里,恶意用户很容易通过构造特殊值篡改数据库,甚至获取敏感数据。 mysql_*函数已被废弃:这个系列的函数早在PHP 5.5就被标记为废弃,PHP 7之后直接被移除,完全不推荐使用,应该换成mysqli或者PDO扩展。
下面给你两个更安全、更可靠的版本:
版本1:改用mysqli预处理语句(分步判断)
// 先建立mysqli连接(替换成你的数据库信息) $conn = mysqli_connect('localhost', '你的用户名', '你的密码', '你的数据库名'); // 先查询是否存在对应记录,用预处理语句避免注入 $stmt = $conn->prepare("SELECT * FROM downloads WHERE name = ?"); // 绑定参数,"s"表示字符串类型 $stmt->bind_param("s", $details['name']); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows === 0) { // 插入新记录 $stmt = $conn->prepare("INSERT INTO downloads (name, idu) VALUES (?, ?)"); $stmt->bind_param("ss", $details['name'], $details['idu']); $stmt->execute(); } else { // 更新现有记录 $stmt = $conn->prepare("UPDATE downloads SET idu = ? WHERE name = ?"); $stmt->bind_param("ss", $details['idu'], $details['name']); $stmt->execute(); } // 清理资源 $stmt->close(); $conn->close();
版本2:用MySQL原生的ON DUPLICATE KEY UPDATE(更高效)
这个方法可以把查询、插入、更新合并成一条语句,还能避免竞态条件(比如在你查询和插入之间,有其他请求插入了相同name的记录),前提是你需要给downloads表的name字段设置唯一索引(UNIQUE KEY)。
$conn = mysqli_connect('localhost', '你的用户名', '你的密码', '你的数据库名'); // 一条语句搞定插入或更新 $stmt = $conn->prepare("INSERT INTO downloads (name, idu) VALUES (?, ?) ON DUPLICATE KEY UPDATE idu = ?"); $stmt->bind_param("sss", $details['name'], $details['idu'], $details['idu']); $stmt->execute(); // 清理资源 $stmt->close(); $conn->close();
这样不仅解决了你的代码运行问题,还从根本上提升了代码的安全性和可靠性。
内容的提问来源于stack exchange,提问作者caweye
相关产品推荐
相关产品推荐

