如何解决MSSQL中TRUNCATE与INSERT的执行顺序竞争问题
解决MSSQL中TRUNCATE未完成就执行INSERT的问题
首先,PDO的query()方法默认同步执行,TRUNCATE作为DDL语句执行后会立即生效(除非处于事务中),但出现旧数据残留的情况,大概率是未确认TRUNCATE执行成功就推进后续逻辑,或是存在连接层面的隐式问题。可以通过以下方式解决:
方案一:先确认TRUNCATE执行成功再继续
修改代码,先校验TRUNCATE的执行结果,仅在成功时才进行API请求和数据插入:
// 执行TRUNCATE并验证结果 $truncateResult = $connPdo->query("TRUNCATE TABLE [Table]"); if (!$truncateResult) { // 处理执行失败的情况,比如终止脚本或记录日志 die("TRUNCATE操作失败"); } // 后续数据获取与插入逻辑 $get_data = callAPI('GET', 'https://api...'); $response = json_decode($get_data, true); foreach ($response['FOO'] as $Lines) { // 注意:此处存在*SQL注入风险*,建议改用预处理语句 $Proginsert = $connPdo->query("INSERT INTO [Table] (FEE, FIE) VALUES('" . $Lines['A'] . "','" . $Lines['B'] . "')"); }
方案二:用事务保证操作的顺序性与原子性
虽然TRUNCATE是DDL语句,但MSSQL支持在事务内执行它,借此可以确保TRUNCATE完成后才执行INSERT,同时保证整个操作的一致性:
try { $connPdo->beginTransaction(); // 执行TRUNCATE $connPdo->exec("TRUNCATE TABLE [Table]"); // 获取外部数据 $get_data = callAPI('GET', 'https://api...'); $response = json_decode($get_data, true); // 使用预处理语句执行批量插入(安全且高效) $insertStmt = $connPdo->prepare("INSERT INTO [Table] (FEE, FIE) VALUES(:fee, :fie)"); foreach ($response['FOO'] as $Lines) { $insertStmt->execute([ ':fee' => $Lines['A'], ':fie' => $Lines['B'] ]); } $connPdo->commit(); } catch (PDOException $e) { $connPdo->rollBack(); die("操作失败:" . $e->getMessage()); }
重要提醒:修复SQL注入漏洞
你的原始代码直接拼接字符串生成SQL语句,存在严重的SQL注入风险。强烈建议使用PDO预处理语句(如方案二中的写法),既能避免安全问题,又能提升批量插入的效率。
内容的提问来源于stack exchange,提问作者Godisbit
相关产品推荐
相关产品推荐

