AJAX调用PHP插入数据出现重复插入问题求助
重复插入数据但仅返回一个ID的问题排查与修复
问题现象
通过AJAX调用save.php插入数据时,每次提交都会触发两次数据库插入操作,但响应仅返回一个ID。
核心原因:数据库函数中SQL被执行两次
查看poke_db函数的代码,发现同一SQL语句被执行了两次:
- 首先通过
$conn->query($sql)执行一次SQL用于错误检查 - 随后又根据
$multi参数,再次调用mysqli_query或mysqli_multi_query执行同一SQL
对于INSERT语句来说,这直接导致数据被插入两次,而返回的ID只是第二次插入的结果,因此仅能看到一个ID。
具体修复点
1. 修正数据库操作函数poke_db
移除重复执行SQL的代码,将错误检查与SQL执行合并:
$srv = "localhost"; $usr = "root"; $pas = "pass"; $db_name = "dbname"; function poke_db($sql,$multi,$array){ global $db_name, $srv, $usr, $pas; $conn = mysqli_init(); $conn->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5); $conn->real_connect($srv, $usr, $pas, $db_name); if ($conn->connect_error) { die('[ERR] '.$conn->connect_error); } $result = null; if( $multi == 1 ){ if( !mysqli_multi_query($conn, $sql) ){ die('[ERR] ' . $conn->error); } $result = true; }else{ $result = mysqli_query($conn, $sql); if( !$result ){ die('[ERR] ' . $conn->error); } $id = mysqli_insert_id($conn); } if( $array == 1 ){ if( mysqli_num_rows($result) != 0 ){ $out_array = []; while($row = mysqli_fetch_assoc($result)){ $out_array[] = $row; } }else{ $out_array = null; } mysqli_free_result($result); $conn->close(); return $out_array; }else{ $conn->close(); if( isset($id) ){ return $id; } return $result; } }
- 移除了多余的
$conn->query($sql)调用,将错误检查合并到实际执行SQL的步骤中 - 添加了数据库连接关闭操作,避免连接泄漏
- 优化了数组初始化逻辑,使用空数组替代未定义变量
2. 修正JavaScript中的语法错误
AJAX请求的data参数存在多余右括号,修正后:
function opnActPag () { var actDiv = document.getElementById('act_div'); var actTxtArea = document.getElementById('act_txt_area'); var actHidVal = document.getElementById('act_hid_val').value; var actHidUsr = document.getElementById('act_hid_usr').value; actDiv.style.display = 'block'; opnActPag['closeActPag'] = function () { actDiv.style.display = 'none'; actTxtArea.value = ''; } opnActPag['addAct'] = function () { $.ajax({ type: 'POST', url: 'save.php', data: { act_txt: actTxtArea.value, id: actHidVal, usr: actHidUsr }, success : function (data) { console.log(data); } }); } }
3. 页面元素ID匹配修正(可选)
页面中清除按钮的id与onclick事件引用的文本框ID不匹配,修正后:
<div class="act-text-btn-no" id="act_clr_txt" onclick="document.getElementById('act_txt_area').value = '';">×</div>
额外安全建议
当前PHP代码存在SQL注入风险,应使用预处理语句替代直接拼接SQL:
<?php $srv = "localhost"; $usr_db = "root"; $pas_db = "pass"; $db_name = "dbname"; if( isset($_POST['act_txt']) && !empty($_POST['act_txt']) ){ $actTxt = preg_replace("/[\r\n]+/", " ", htmlentities(trim($_POST['act_txt']), ENT_QUOTES)); $usr = $_POST['usr']; $id = $_POST['id']; // 检查重复的预处理语句 $conn = mysqli_init(); $conn->real_connect($srv, $usr_db, $pas_db, $db_name); $stmt = $conn->prepare("SELECT COUNT(*) as count FROM actions WHERE user_name = ? AND info = ? AND level_3_id = ?"); $stmt->bind_param("ssi", $usr, $actTxt, $id); $stmt->execute(); $result = $stmt->get_result(); $ret = $result->fetch_assoc(); if( $ret['count'] == 0 ){ // 插入数据的预处理语句 $stmt = $conn->prepare("INSERT INTO actions (user_name, info, level_3_id) VALUES (?, ?, ?)"); $stmt->bind_param("ssi", $usr, $actTxt, $id); $stmt->execute(); $ret = $stmt->insert_id; } echo $ret; $conn->close(); } ?>
内容的提问来源于stack exchange,提问作者Blackegg13
相关产品推荐
相关产品推荐

