更新为当前尝试码
hi_我试图做一个PDO检查行值,然后在表中的一行上的更新语句,使用来自我的数据库中不同表的行值,在事务内,但我不断得到一个错误。
我有两个表,它们是table1
和bank
。
table1
包含userid
和ticketamount
列。
bank
包含userid
和goldbalance
列。
ticketamount
和goldbalance
是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
。
在这两者之间,您可以执行字符串变量的echo
或var_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将抛出错误。(如果userid
在bank
表中是唯一的,这不会有什么区别。如果它不是唯一的,我们想要哪一行?最新的,最有价值的,如黄金天平等。我们可以添加一个聚合或ORDER BY,使其更具确定性。
还有一个问题,如果一行没有返回,我们将得到一个NULL值,当我们添加一个NULL时,我们得到一个NULL作为结果。我们想要处理缺失行或NULL值为零吗?
如果userid
在bank
表中是唯一的,我将使用连接操作执行此查询。为了模拟子查询,我们需要一个外部连接,例如
由于没有一个标识符是保留字,所以我们不需要在标识符周围加上反号。
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
关键字)