You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AJAX调用PHP插入数据出现重复插入问题求助

重复插入数据但仅返回一个ID的问题排查与修复

问题现象

通过AJAX调用save.php插入数据时,每次提交都会触发两次数据库插入操作,但响应仅返回一个ID。

核心原因:数据库函数中SQL被执行两次

查看poke_db函数的代码,发现同一SQL语句被执行了两次:

  1. 首先通过$conn->query($sql)执行一次SQL用于错误检查
  2. 随后又根据$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 = '';">&times;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 13:24:57