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

CSV映射导入数据至双表的PDO SQL查询构建问题

双表批量插入解决方案

要实现同时向products和product_details表插入数据,核心是保证两张表的记录能正确关联(通常通过products的主键,比如product_id),同时必须修复原有代码的SQL注入风险,并通过事务确保数据一致性。以下是两种可行方案:

方案一:逐行插入(适合小数据量)

逐行插入products后,立刻获取自增主键product_id,再插入product_details,用事务包裹确保原子性。

if(isset($_POST["sku"]))
{
    session_start();
    $connect = new PDO("mysql:host=localhost; dbname=feed_import", "feed_import", "tSpIn35M");
    // 开启事务,保证数据一致性
    $connect->beginTransaction();

    try {
        $file_data = $_SESSION['file_data'];
        unset($_SESSION['file_data']);

        // 预处理products插入语句(参数绑定避免SQL注入)
        $productStmt = $connect->prepare("
            INSERT INTO products 
            (sku, category_id, price, discount_rate, vat_rate, stock, external_link)
            VALUES (:sku, :category_id, :price, :discount_rate, :vat_rate, :stock, :external_link)
        ");

        // 预处理product_details插入语句
        $detailStmt = $connect->prepare("
            INSERT INTO product_details 
            (product_id, title, description)
            VALUES (:product_id, :title, :description)
        ");

        foreach($file_data as $row)
        {
            // 绑定products参数
            $productStmt->bindValue(':sku', $row[$_POST["sku"]]);
            $productStmt->bindValue(':category_id', $row[$_POST["category_id"]]);
            $productStmt->bindValue(':price', $row[$_POST["price"]]);
            $productStmt->bindValue(':discount_rate', $row[$_POST["discount_rate"]]);
            $productStmt->bindValue(':vat_rate', $row[$_POST["vat_rate"]]);
            $productStmt->bindValue(':stock', $row[$_POST["stock"]]);
            $productStmt->bindValue(':external_link', $row[$_POST["external_link"]]);
            $productStmt->execute();

            // 获取刚插入的product_id(自增主键)
            $productId = $connect->lastInsertId();

            // 绑定product_details参数并插入
            $detailStmt->bindValue(':product_id', $productId);
            $detailStmt->bindValue(':title', $row[$_POST["title"]]);
            $detailStmt->bindValue(':description', $row[$_POST["description"]]);
            $detailStmt->execute();
        }

        // 提交事务
        $connect->commit();
        echo 'Data Imported Successfully';
    } catch(PDOException $e) {
        // 出错则回滚所有操作
        $connect->rollBack();
        echo 'Import Failed: ' . $e->getMessage();
    }
}

方案二:批量插入+关联查询(适合大数据量)

先批量插入products,再通过唯一字段sku关联获取product_id,批量插入product_details,效率更高。

if(isset($_POST["sku"]))
{
    session_start();
    $connect = new PDO("mysql:host=localhost; dbname=feed_import", "feed_import", "tSpIn35M");
    $connect->beginTransaction();

    try {
        $file_data = $_SESSION['file_data'];
        unset($_SESSION['file_data']);

        // 准备批量插入products的参数
        $productValues = [];
        $productParams = [];
        foreach($file_data as $row)
        {
            $productValues[] = "(?, ?, ?, ?, ?, ?, ?)";
            $productParams[] = $row[$_POST["sku"]];
            $productParams[] = $row[$_POST["category_id"]];
            $productParams[] = $row[$_POST["price"]];
            $productParams[] = $row[$_POST["discount_rate"]];
            $productParams[] = $row[$_POST["vat_rate"]];
            $productParams[] = $row[$_POST["stock"]];
            $productParams[] = $row[$_POST["external_link"]];
        }

        // 执行products批量插入
        $productQuery = "
            INSERT INTO products 
            (sku, category_id, price, discount_rate, vat_rate, stock, external_link)
            VALUES " . implode(',', $productValues);
        $productStmt = $connect->prepare($productQuery);
        $productStmt->execute($productParams);

        // 准备批量插入product_details的参数(通过sku关联product_id)
        $detailValues = [];
        $detailParams = [];
        foreach($file_data as $row)
        {
            $detailValues[] = "(
                (SELECT product_id FROM products WHERE sku = ?),
                ?,
                ?
            )";
            $detailParams[] = $row[$_POST["sku"]];
            $detailParams[] = $row[$_POST["title"]];
            $detailParams[] = $row[$_POST["description"]];
        }

        // 执行product_details批量插入
        $detailQuery = "
            INSERT INTO product_details 
            (product_id, title, description)
            VALUES " . implode(',', $detailValues);
        $detailStmt = $connect->prepare($detailQuery);
        $detailStmt->execute($detailParams);

        $connect->commit();
        echo 'Data Imported Successfully';
    } catch(PDOException $e) {
        $connect->rollBack();
        echo 'Import Failed: ' . $e->getMessage();
    }
}

关键注意事项

  • SQL注入防护:必须使用PDO参数绑定,绝对不能直接拼接用户输入到SQL语句中,原有代码存在严重安全漏洞。
  • 事务处理:所有插入操作必须放在事务中,避免出现一张表插入成功、另一张失败的不一致情况。
  • 关联约束:确保product_details表存在product_id外键字段,关联products表的主键;如果用sku关联,必须给products.sku添加唯一约束。
  • 字段类型匹配:插入的数据类型要和数据库表定义一致(比如price是数值类型,PDO会自动处理类型转换)。

内容的提问来源于stack exchange,提问作者Marcin Wierzycki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:40:37