使用来自不同表的另一行的值对一行进行PDO事务更新错误


PDO Transaction Update Error on a row using the value of another row from a different table

更新为当前尝试码

hi_我试图做一个PDO检查行值,然后在表中的一行上的更新语句,使用来自我的数据库中不同表的行值,在事务内,但我不断得到一个错误。

我有两个表,它们是table1bank

table1包含useridticketamount列。

bank包含useridgoldbalance列。

ticketamountgoldbalance是int。这两行从来不是NULL,当创建用户帐户时,0的值被输入到这些行中,因此它们中总是有一个值。

userid是唯一列。

我想做的是运行一个PDO事务,该事务将通过添加存储在goldbalance中的任何值来更新ticketamount,我试图通过将其设置为ticketamount + (some code to fetch the goldbalance amount here)来做到这一点。

这是我的代码全文:

<?php
$servername = "myservername";
$username = "myusername";
$password = "mypassword";
$dbname = "mydbname";
try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    // set the PDO error mode to exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// first, find out if bank.goldbalance is > 0, if it is, then run Update statements and echo "1", else echo "0":
    $stmt = $conn->prepare("SELECT 'goldbalance' FROM 'bank' WHERE 'userid' = :id");
    $stmt->bindParam(':id', $userid);
    $userid = $_POST['userid'];
    $stmt->execute();
 if (($result['goldbalance']) > 0){
// if bank.goldbalance is greater than 0, then run this transaction:
    $conn->beginTransaction();
    // prepare UPDATE statement
    $sql = 'UPDATE table1 t
     LEFT JOIN bank b
     ON b.userid = t.userid
     SET t.ticketamount = t.ticketamount + b.goldbalance
     WHERE t.userid = :id';
    echo "SQL=" . $sql ;
    // prepare statement and bind parameters
    $stmt = $conn->prepare($sql); 
    $stmt->bindParam(':id', $userid);
    $userid = $_POST['userid'];
    $stmt->execute();
    // 2nd statement...
    $stmt = $conn->prepare("UPDATE 'bank' SET 'goldbalance' = 0 WHERE 'userid' = :id");
    $stmt->bindParam(':id', $userid);
    $userid = $_POST['userid'];
    $stmt->execute();
    $conn->commit();
    // echo "1" to verify transaction completed
    echo "1";
} else {
    echo '0';
}
        }
    catch(PDOException $e)
        {
        echo "Error: " . $e->getMessage();
        }
    $conn = null;
    ?>
如果银行

。goldbalance = 0,那么运行交易就没有意义了,所以我想先检查一下,如果它= 0,那么我只想回显"0",但如果它=>0,那么我想运行交易,并在交易完成时回显"1"。

我正试图使交易取银行里的价值。然后将其添加到table1.ticketamount中的值。然后,交易的第二部分应该设置银行。Goldbalance必须为"0"。

我现在在控制台中得到的响应是上面的代码:

"Error: SQLSTATE[42000]: Syntax Error or access violation: 1064 SQL语法错误;查看与MySQL服务器版本对应的手册,以便在第1行"bank"WHERE"userid"="113234523347"附近使用正确的语法

我看不出这段代码有什么问题。

在这个问题上任何额外的建议都会很好。提前感谢!

要调试它,请将其分成两个步骤。首先,将SQL语句的文本作为字符串生成到变量中。

然后,将变量传递给prepare

在这两者之间,您可以执行字符串变量的echovar_dump


在您的例子中,这是一个简单的PHP字符串字面值/连接问题。

第二个双引号结束字符串字面量,下面的SELECT ...不被PHP识别。

$stmt = $conn->prepare("UPDATE 'table1' 
        SET 'ticketamount' = 'ticketamount'+("SELECT 'goldbalance'
                                             ^                     

单引号有问题;对于MySQL,这些应该是标识符

周围的反号

由于您没有在字符串中包含任何变量,因此它是一个静态文字(就SQL而言,这是一件非常好的事情),因此您可以使用单引号而不是双引号:

$sql = 'UPDATE `table1` t
           SET t.`ticketamount` = t.`ticketamount` 
                                + ( SELECT b.`goldbalance`
                                      FROM `bank` b
                                     WHERE b.`userid` = :id1
                                     LIMIT 1
                                  )
          WHERE t.`userid` = :id2';
#echo "SQL=" . $sql ;
$stmt = $conn->prepare($sql);

请注意,在PDO语句中多次使用相同的绑定变量名称会出现问题(至少过去是这样),因为PDO实际上是将其从命名表示法转换为位置表示法。

我还在子查询中添加了LIMIT 1子句,因为如果我们返回多个行,MySQL将抛出错误。(如果useridbank表中是唯一的,这不会有什么区别。如果它不是唯一的,我们想要哪一行?最新的,最有价值的,如黄金天平等。我们可以添加一个聚合或ORDER BY,使其更具确定性。

还有一个问题,如果一行没有返回,我们将得到一个NULL值,当我们添加一个NULL时,我们得到一个NULL作为结果。我们想要处理缺失行或NULL值为零吗?

如果useridbank表中是唯一的,我将使用连接操作执行此查询。为了模拟子查询,我们需要一个外部连接,例如

由于没有一个标识符是保留字,所以我们不需要在标识符周围加上反号。

  UPDATE table1 t
    LEFT
    JOIN bank b
      ON b.userid = t.userid
     SET t.ticketamount = t.ticketmamount + IFNULL(b.goldbalance,0)
   WHERE t.userid = :id

如果我们想要模拟原始查询,我们需要从b.goldbalance周围删除IFNULL包装器,以便它可以返回NULL,因此ticketamount将设置为NULL。

如果我们不想更新行,如果相关行从银行"丢失",我们可以做一个内连接而不是一个外连接(即删除LEFT关键字)