如何通过PHP+AJAX同时向两张数据库表插入数据?
问题分析与修复方案
首先可以明确:AJAX完全可以实现双表插入操作,你的问题全部出在PHP代码的逻辑和语法错误上,我帮你拆解核心问题并给出修复方案:
核心问题拆解
重复
prepare覆盖了第一个插入语句
你连续调用两次$DBcon->prepare(),第二次调用直接覆盖了$stmt变量,导致pm_outbox的插入语句根本没被执行——只有最后一次prepare的pm_imbox语句得到了执行。占位符与绑定逻辑不匹配
你用了bindparam()绑定命名占位符(比如:to_username),但SQL语句里却直接拼接变量(比如'$userid'),这不仅让bindparam()完全失效,还存在严重的SQL注入风险。另外第二个INSERT语句里的'to_username'是字符串字面量,不是变量$to_username,这也是明显错误。
修复后的PHP代码
我们需要分开处理两个插入语句,正确使用占位符,同时加入事务确保操作的原子性:
<?php require_once "db.php"; // 接收POST提交的数据 $to_username = $_POST['to_username']; $title = $_POST['title']; $message = $_POST['message']; $to_userid = $_POST['to_userid']; $userid = $_POST['userid']; $request_id = $_POST['request_id']; $from_username = $_POST['from_username']; $senddate = $_POST['senddate']; try { // 开启事务:确保两个插入操作要么都成功,要么都失败 $DBcon->beginTransaction(); // 处理pm_outbox表的插入 $stmtOutbox = $DBcon->prepare("INSERT INTO pm_outbox(userid, username, to_userid, to_username, title, content, ReqID, senddate) VALUES(:userid, :from_username, :to_userid, :to_username, :title, :message, :request_id, :senddate)"); $stmtOutbox->bindParam(':userid', $userid); $stmtOutbox->bindParam(':from_username', $from_username); $stmtOutbox->bindParam(':to_userid', $to_userid); $stmtOutbox->bindParam(':to_username', $to_username); $stmtOutbox->bindParam(':title', $title); $stmtOutbox->bindParam(':message', $message); $stmtOutbox->bindParam(':request_id', $request_id); $stmtOutbox->bindParam(':senddate', $senddate); $stmtOutbox->execute(); // 处理pm_imbox表的插入 $stmtImbox = $DBcon->prepare("INSERT INTO pm_imbox(userid, username, from_id, from_username, title, content, ReqID, recieve_date) VALUES(:to_userid, :to_username, :userid, :from_username, :title, :message, :request_id, :senddate)"); $stmtImbox->bindParam(':to_userid', $to_userid); $stmtImbox->bindParam(':to_username', $to_username); $stmtImbox->bindParam(':userid', $userid); $stmtImbox->bindParam(':from_username', $from_username); $stmtImbox->bindParam(':title', $title); $stmtImbox->bindParam(':message', $message); $stmtImbox->bindParam(':request_id', $request_id); $stmtImbox->bindParam(':senddate', $senddate); $stmtImbox->execute(); // 提交事务 $DBcon->commit(); $res = "Data Inserted Successfully:"; echo json_encode($res); } catch(PDOException $e) { // 出错时回滚事务,撤销所有操作 $DBcon->rollBack(); $error = "Not Inserted, Some Problem occurred: " . $e->getMessage(); echo json_encode($error); } ?>
关键修复点说明
- 用两个独立变量(
$stmtOutbox和$stmtImbox)存储两个prepare语句,避免覆盖 - SQL语句使用命名占位符,通过
bindParam()绑定变量,彻底杜绝SQL注入 - 加入事务处理,保证双表插入的原子性,不会出现一个表成功另一个失败的情况
- 修复了第二个INSERT语句中
'to_username'的字符串字面量错误 - 加入异常捕获,方便排查具体错误
AJAX代码小优化
你的AJAX代码本身没问题,可增加小优化提升用户体验:
<script type="text/javascript"> function insertData() { var to_username = $("#to_username").val(); var title = $("#title").val(); var message = $("#message").val(); var to_userid = $("#to_userid").val(); var userid = $("#userid").val(); var request_id = $("#request_id").val(); var from_username = $("#from_username").val(); var senddate = $("#senddate").val(); // 清空之前的提示信息 $("#message").html(""); $("p").removeClass("alert alert-success"); $.ajax({ type: "POST", url: "reply_process.php", data: { to_username: to_username, title: title, message: message, to_userid: to_userid, userid: userid, request_id: request_id, from_username: from_username, senddate: senddate }, dataType: "JSON", success: function(data) { $("#message").html(data); $("p").addClass("alert alert-success"); }, error: function(err) { alert("请求出错:" + err.responseText); } }); } </script>
这样修改后,双表插入应该就能正常工作了,代码的安全性和健壮性也得到了提升。
内容的提问来源于stack exchange,提问作者Irwin Kumwenda
相关产品推荐
相关产品推荐

