我有两个相互依赖的查询,即如果不执行第一个查询则不应该执行第二个查询,而如果第二个不能执行第二个查询则不应该执行第一个查询。
INSERT INTO `table` VALUES (1,2,3)
UPDATE `otherTable` SET `val1`=1 WHERE `id`=$idOfInsert
ON DUPLICATE KEY UPDATE
不是answear。
我尝试使用mysqli::multi_query
,但事实证明它执行第一个,即使第二个无法执行(它会在出错时停止)。
如果我说的不清楚,请向我询问更多信息。
有人可以帮我吗?
答案 0 :(得分:4)
如果您使用的引擎支持它(InnoDB,BDB),您可以使用事务。
有关示例,请参阅http://dev.mysql.com/doc/refman/5.0/en/commit.html。
编辑:使用 mysqli 的快速示例:
$connection->autocommit(FALSE); // disable auto-commit and start a new transaction
$result = $connection->query("INSERT INTO `table` VALUES (1,2,3)");
$result &= $connection->query("UPDATE `otherTable` SET `val1`=1 WHERE `id`=$idOfInsert");
if (!$result) {
// One of the queries has failed: cancel the transaction
$connection->rollback();
} else {
// Both queries worked:commit the current transaction
$connection->commit();
}
$connection->autocommit(TRUE); // enable auto-commit
您可能希望优化查询(即如果第一个失败则不执行第二个查询,使用预准备语句,......)
答案 1 :(得分:1)
我正在寻找的是交易。那时@tmuguet的答案确实对我有帮助,但是现在从时间的角度来看,我想提供一个更新的答案。
每个查询需要单独执行,并使用准备好的语句来防止SQL注入。
try {
// Start transaction
$mysqli->begin_transaction();
$mysqli->query('INSERT INTO `table` VALUES (1,2,3)');
$stmt = $mysqli->prepare('UPDATE otherTable SET val1=1 WHERE id=?');
$stmt->bind_param('s', $idOfInsert);
$stmt->execute();
// Commit changes
$mysqli->commit();
} catch (\Throwable $e) {
// Something went wrong. Rollback
$mysqli->rollback();
throw $e;
}
当然要使其正常工作,您需要启用mysqli错误报告。只需在代码中new mysqli()
之前添加此行即可。
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
答案 2 :(得分:-1)
使用[INSERT IGNORE]使SQL服务器忽略错误。
INSERT IGNORE INTO `table` VALUES (1,2,3);
然后使用LAST_INSERT_ID()获取插入的ID,如果没有插入则使用0。如果没有ID = 0的记录,这将使UPDATE失败。
UPDATE `otherTable` SET `val1`=1 WHERE `id`=LAST_INSERT_ID();
答案 3 :(得分:-2)
将其分成多个查询调用:
$result = mysql_query("INSERT ...");
if ($result) {
mysql_query("UPDATE ...");
}
但是“如果不能做第二次就不要做”是不可能的。 PHP无法及时返回并警告第一个查询第二个查询失败。