如何使用prepare语句在MySQLi中考虑事务将数据插入到三个不同的表中

时间:2017-07-23 21:41:33

标签: php mysqli

同时执行以下SQL语句的最完美和最安全的方法是,考虑到MySQLi中的事务,以便将数据添加到所有表中,或者当添加过程发生故障时需要回滚数据桌子上有一个。

$conn = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);

 $stmt1 = $conn->prepare("INSERT INTO stdHouseholder (usersID, parentJob, phoneNumber,address) VALUES (?, ?, ?, ?)");
$stmt1->bind_param("ssss", $userId, $parentJob, $phoneB, $addressB);

$stmt2 = $conn->prepare("INSERT INTO stdConfirmInfo (usersID, commitment, credentials, haveOfficialLetter) VALUES (?, ?, ?, ?)");
$stmt2->bind_param("ssss", $userId, $commitment, $credentials, $NamesEnglish);

 $stmt3 = $conn->prepare("INSERT INTO users_roleTB (usersID, role_id) VALUES (?, ?)");
$stmt3->bind_param("ss", $userId, $role_id);

2 个答案:

答案 0 :(得分:1)

您可以使用mysqli命令的begin transactioncommitrollback功能来帮助您。

您需要启动一个事务,检查每个插入查询的结果然后提交(如果它们都表现良好)或者如果它们没有执行则回滚:

<?php

$conn = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);

$stmt1 = $conn->prepare("INSERT INTO stdHouseholder (usersID, parentJob, phoneNumber,address) VALUES (?, ?, ?, ?)");
$stmt1->bind_param("ssss", $userId, $parentJob, $phoneB, $addressB);

$stmt2 = $conn->prepare("INSERT INTO stdConfirmInfo (usersID, commitment, credentials, haveOfficialLetter) VALUES (?, ?, ?, ?)");
$stmt2->bind_param("ssss", $userId, $commitment, $credentials, $NamesEnglish);

$stmt3 = $conn->prepare("INSERT INTO users_roleTB (usersID, role_id) VALUES (?, ?)");
$stmt3->bind_param("ss", $userId, $role_id);

$conn->begin_transaction();
if ($stmt1->execute() && $stmt2->execute() && $stmt3->execute()) {
    $conn->commit();
} else {
    $conn->rollback();
}

$conn->close();

答案 1 :(得分:0)

You can't insert to multiple tables in one statement

您必须将它们放入交易中

$conn = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);

$conn->query("BEGIN;");
$failed = false;
$stmt1 = $conn->prepare("INSERT INTO stdHouseholder (usersID, parentJob, phoneNumber,address) VALUES (?, ?, ?, ?)");
$stmt1->bind_param("ssss", $userId, $parentJob, $phoneB, $addressB);
if (!$stmt2->execute()) {
    $failed = true;
    $conn->query("ROLLBACK;");
}
if(!$failed){
    $stmt2 = $conn->prepare("INSERT INTO stdConfirmInfo (usersID, commitment, credentials, haveOfficialLetter) VALUES (?, ?, ?, ?)");
    $stmt2->bind_param("ssss", $userId, $commitment, $credentials, $NamesEnglish);
     if (!$stmt2->execute()) {
         $failed = true;
         $conn->query("ROLLBACK;");
     }
}
if(!$failed){
    $stmt3 = $conn->prepare("INSERT INTO users_roleTB (usersID, role_id) VALUES (?, ?)");
    $stmt3->bind_param("ss", $userId, $role_id);
    if (!$stmt3->execute()) {
        $failed = true;
        $conn->query("ROLLBACK;");
    }
}
if(!$failed){
    $conn->query("COMMIT;");
}

锁定表?

如果你想在锁定表时进行交易,你将需要另一个approach,因为锁定一个表将提交任何正在运行的交易,这是可怕的

在这种情况下,您将通过关闭mysql的自动提交功能

来启动事务
SET autocommit=0;

然后锁定你的表

LOCK TABLES stdHouseholder WRITE, stdConfirmInfo WRITE, users_roleTB WRITE;

然后正常运行准备好的陈述

$stmt->execute();

最后,如果语句成功,则提交事务,然后再次转动自动提交on

 $conn->query("COMMIT;");
 $conn->query("SET autocommit=1;");

请注意,如果您未提交(并且未回滚),则会话结束时将回滚事务(but this is not guaranteed)。