MySQL双表数据同步问题:JSON数据实现新增/更新逻辑
问题解决方案与代码错误分析
一、核心逻辑实现思路
三个表通过userid关联,判断客户是否存在的核心依据是**tblcustomfieldsvalues.value字段的唯一客户编码**(业务唯一标识),以此展开「存在则更新,不存在则插入」的逻辑:
- 存在:通过编码找到对应的
relid(即tblclients.userid),更新tblclients和tblcontacts的对应数据 - 不存在:先插入
tblclients获取自增userid,再依次插入tblcustomfieldsvalues和tblcontacts关联数据
二、现有插入代码的典型错误
假设你的现有代码类似以下结构,这些是高频问题:
// 错误示例代码 $jsonData = json_decode($curlResponse, true); // 错误1:$email未赋值就执行判断 if (empty($email)) { $email = $jsonData['email']; } // 错误2:变量重复使用,$userid既存查询结果集又存自增ID $userid = mysqli_query($conn, "SELECT userid FROM tblclients WHERE email = '$email'"); // 错误3:直接拼接外部数据,存在SQL注入风险 mysqli_query($conn, "INSERT INTO tblclients (name, email) VALUES ('{$jsonData['name']}', '$email')"); $userid = mysqli_insert_id($conn); // 错误4:未检查数据库操作结果,无错误排查能力 mysqli_query($conn, "INSERT INTO tblcustomfieldsvalues (relid, value) VALUES ('$userid', '{$jsonData['customercode']}')");
对应错误点:
- 未赋值就判断变量:
$email还未从JSON提取就执行empty($email),逻辑完全颠倒 - 变量重复覆盖:同一个
$userid既存储查询结果对象,又存储自增ID数值,导致后续逻辑混乱 - SQL注入风险:直接将外部JSON数据拼接进SQL语句,未做参数绑定处理
- 缺乏错误处理:没有检查数据库操作的返回结果,无法定位插入失败原因
- 关联逻辑缺失:未通过唯一客户编码判断存在性,直接插入会产生重复数据
三、完整实现代码
<?php // 假设已建立mysqli数据库连接$conn $jsonData = json_decode($curlResponse, true); $customercode = $jsonData['customercode']; $clientName = $jsonData['name']; $clientEmail = $jsonData['email']; $contactPhone = $jsonData['contact_phone']; // 第一步:通过唯一客户编码查询是否存在该客户 $stmt = $conn->prepare("SELECT relid FROM tblcustomfieldsvalues WHERE value = ?"); $stmt->bind_param("s", $customercode); $stmt->execute(); $result = $stmt->get_result(); $existingUserId = null; if ($result->num_rows > 0) { // 客户存在,更新关联表数据 $row = $result->fetch_assoc(); $existingUserId = $row['relid']; // 更新tblclients $stmtUpdateClient = $conn->prepare("UPDATE tblclients SET name = ?, email = ? WHERE userid = ?"); $stmtUpdateClient->bind_param("ssi", $clientName, $clientEmail, $existingUserId); $stmtUpdateClient->execute(); $stmtUpdateClient->close(); // 更新tblcontacts(可根据实际业务调整更新字段和条件) $stmtUpdateContact = $conn->prepare("UPDATE tblcontacts SET phone = ? WHERE userid = ?"); $stmtUpdateContact->bind_param("si", $contactPhone, $existingUserId); $stmtUpdateContact->execute(); $stmtUpdateContact->close(); } else { // 客户不存在,插入关联表数据 // 插入tblclients并获取自增userid $stmtInsertClient = $conn->prepare("INSERT INTO tblclients (name, email) VALUES (?, ?)"); $stmtInsertClient->bind_param("ss", $clientName, $clientEmail); $stmtInsertClient->execute(); $newUserId = $conn->insert_id; $stmtInsertClient->close(); // 插入tblcustomfieldsvalues $stmtInsertCustom = $conn->prepare("INSERT INTO tblcustomfieldsvalues (relid, value) VALUES (?, ?)"); $stmtInsertCustom->bind_param("is", $newUserId, $customercode); $stmtInsertCustom->execute(); $stmtInsertCustom->close(); // 插入tblcontacts $stmtInsertContact = $conn->prepare("INSERT INTO tblcontacts (userid, phone) VALUES (?, ?)"); $stmtInsertContact->bind_param("is", $newUserId, $contactPhone); $stmtInsertContact->execute(); $stmtInsertContact->close(); } // 释放资源 $stmt->close(); $conn->close(); ?>
四、关键说明
- 存在性判断标准:优先使用业务唯一的客户编码,而非邮箱或名称(邮箱可变更、名称易重复)
- 安全处理:全程使用mysqli预处理语句绑定参数,彻底规避SQL注入
- 变量隔离:用
$existingUserId和$newUserId分别存储已有客户ID和新增客户ID,避免变量覆盖 - 调试建议:可在每个数据库操作后添加
if (!$stmt->execute()) { echo $stmt->error; }捕获错误,方便排查问题
内容的提问来源于stack exchange,提问作者imp
相关产品推荐
相关产品推荐

