PHP/Mysqli批量插入不重复记录:Ajax JSON数据场景实现
PHP/Mysqli批量插入不重复记录(处理嵌套JSON数据)
没问题,我来帮你搞定这个批量插入的需求,还要确保只插不存在的记录,同时处理你给的嵌套JSON结构。下面是一步步的实现方案:
1. 先理清楚需求核心
你需要接收这样的JSON数据:
{"add":{"abc":"123","name":"CompanyName","user_id":"1","portfolios":[{"portfolio_id":"1"},{"portfolio_id":"2"},{"portfolio_id":"3"}]}}
然后把它拆成3条独立记录插入表中,每条记录包含abc、name、user_id、portfolio_id四个字段,并且只插入数据库中不存在的记录,重复的要返回失败提示。
2. 数据库准备(关键!)
首先必须给你的表加一个唯一约束,用来判断记录是否重复。假设你业务里的唯一标识是user_id + portfolio_id的组合(你可以根据实际业务调整),执行这条SQL:
ALTER TABLE your_table_name ADD UNIQUE KEY unique_user_portfolio (user_id, portfolio_id);
有了这个约束,我们才能准确识别重复记录。
3. 完整PHP实现代码
下面是结合Mysqli的安全实现,用预处理语句避免SQL注入,同时处理重复判断:
<?php // 1. 数据库连接(替换成你的数据库信息) $mysqli = new mysqli('localhost', 'your_username', 'your_password', 'your_database'); if ($mysqli->connect_error) { die(json_encode(['status' => 'error', 'message' => '数据库连接失败: ' . $mysqli->connect_error])); } // 2. 接收并解析Ajax传来的JSON数据 $json_input = file_get_contents('php://input'); $request_data = json_decode($json_input, true); // 3. 验证输入数据的合法性 if (!isset($request_data['add'], $request_data['add']['abc'], $request_data['add']['name'], $request_data['add']['user_id'], $request_data['add']['portfolios']) || !is_array($request_data['add']['portfolios'])) { echo json_encode(['status' => 'error', 'message' => '输入数据格式不正确']); $mysqli->close(); exit; } // 4. 提取基础字段和portfolio列表 $base_fields = [ 'abc' => $request_data['add']['abc'], 'name' => $request_data['add']['name'], 'user_id' => $request_data['add']['user_id'] ]; $portfolio_list = $request_data['add']['portfolios']; // 5. 整理待插入的记录数组 $all_records = []; $portfolio_ids = []; foreach ($portfolio_list as $item) { if (isset($item['portfolio_id'])) { $all_records[] = [ ...$base_fields, 'portfolio_id' => $item['portfolio_id'] ]; $portfolio_ids[] = $item['portfolio_id']; } } if (empty($all_records)) { echo json_encode(['status' => 'error', 'message' => '没有有效的记录需要插入']); $mysqli->close(); exit; } // 6. 查询数据库中已存在的记录 $placeholders = implode(',', array_fill(0, count($portfolio_ids), '?')); $check_sql = "SELECT portfolio_id FROM your_table_name WHERE user_id = ? AND portfolio_id IN ($placeholders)"; $stmt = $mysqli->prepare($check_sql); // 绑定参数(注意:如果user_id/portfolio_id是字符串,把类型符从'i'改成's') $param_types = 'i' . str_repeat('i', count($portfolio_ids)); $params = array_merge([$param_types, $base_fields['user_id']], $portfolio_ids); call_user_func_array([$stmt, 'bind_param'], $params); $stmt->execute(); $result = $stmt->get_result(); $existing_ids = []; while ($row = $result->fetch_assoc()) { $existing_ids[] = $row['portfolio_id']; } $stmt->close(); // 7. 筛选出需要插入的新记录 $new_records = array_filter($all_records, function($record) use ($existing_ids) { return !in_array($record['portfolio_id'], $existing_ids); }); if (empty($new_records)) { echo json_encode([ 'status' => 'error', 'message' => '所有记录都已存在', 'existing_portfolio_ids' => $existing_ids ]); $mysqli->close(); exit; } // 8. 批量插入新记录 $columns = implode(',', array_keys($new_records[0])); $value_groups = []; $insert_params = []; $insert_types = ''; foreach ($new_records as $record) { $value_groups[] = '(' . implode(',', array_fill(0, count($record), '?')) . ')'; foreach ($record as $val) { $insert_params[] = $val; // 根据字段类型设置类型符:整数'i',字符串's',浮点'd' $insert_types .= is_int($val) ? 'i' : 's'; } } $insert_sql = "INSERT INTO your_table_name ($columns) VALUES " . implode(',', $value_groups); $stmt = $mysqli->prepare($insert_sql); call_user_func_array([$stmt, 'bind_param'], array_merge([$insert_types], $insert_params)); if ($stmt->execute()) { $inserted_count = $stmt->affected_rows; echo json_encode([ 'status' => 'success', 'message' => "成功插入 $inserted_count 条记录", 'inserted_records' => $new_records, 'existing_portfolio_ids' => $existing_ids ]); } else { echo json_encode(['status' => 'error', 'message' => '插入失败: ' . $stmt->error]); } // 9. 关闭连接 $stmt->close(); $mysqli->close(); ?>
4. 关键细节说明
- SQL注入防护:全程使用Mysqli预处理语句,避免直接拼接SQL字符串。
- 重复判断逻辑:先批量查询已存在的记录,再筛选出需要插入的新记录,比逐条判断效率高很多。
- 返回结果:接口会返回清晰的JSON格式结果,包含成功/失败状态、提示信息,以及已存在的ID列表,方便前端处理。
- 字段类型适配:代码里默认
user_id和portfolio_id是整数,如果你的字段是字符串,记得把参数类型符从i改成s。
内容的提问来源于stack exchange,提问作者Philipp M
相关产品推荐
相关产品推荐

