Php 使用另一个表中另一行的值的行上的PDO事务更新错误
使用当前尝试代码更新 您好,我正在尝试对行值进行PDO检查,然后对表中的行执行Update语句,使用来自数据库中不同表的行的值,在事务内部执行,但我一直收到错误消息 我有两个表,它们是Php 使用另一个表中另一行的值的行上的PDO事务更新错误,php,mysql,if-statement,pdo,Php,Mysql,If Statement,Pdo,使用当前尝试代码更新 您好,我正在尝试对行值进行PDO检查,然后对表中的行执行Update语句,使用来自数据库中不同表的行的值,在事务内部执行,但我一直收到错误消息 我有两个表,它们是table1和bank table1包含列userid和ticketamount bank包含列userid和goldbalance ticketamount和goldbalance是整数。 这两行永远不会为NULL,创建用户帐户时,会在这些行中输入0的值,因此这些行中始终会有一个值 userid是唯一的列 我想做
table1
和bank
table1
包含列userid
和ticketamount
bank
包含列userid
和goldbalance
ticketamount
和goldbalance
是整数。
这两行永远不会为NULL
,创建用户帐户时,会在这些行中输入0
的值,因此这些行中始终会有一个值
userid
是唯一的列
我想做的是运行一个PDO事务,它将通过添加存储在goldbalance
中的任何值来更新ticketamount
,我正试图通过将其设置为ticketamount+(一些代码在这里获取goldbalance金额)
这是我的完整代码:
<?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;
?>
如果bank.goldbalance=0,那么运行事务就没有意义了,所以我想先检查一下,如果bank.goldbalance=0,那么我只想回显“0”,但如果它=>0,那么我想运行事务,并在事务完成时回显“1”
我试图让交易获取bank.goldbalance中的值,然后将其添加到表1.ticketamount中的值。然后,事务的第二部分应将bank.goldbalance设置为“0”
我现在在控制台中得到的上面代码的响应是:
“错误:SQLSTATE[42000]:语法错误或访问冲突:1064您的SQL语法有错误;请查看与您的MySQL服务器版本对应的手册,以了解在第1行的”“bank”“附近使用的正确语法,其中”“userid”“='11323452347”“。”
我看不出这段代码有什么问题
关于这个问题的任何其他建议都非常好,
提前谢谢 要调试它,请将其分为两个步骤。首先,将SQL语句的文本作为字符串生成到变量中 然后,将变量传递给
prepare
在这两者之间,您可以对字符串变量执行echo
或var\u dump
在您的例子中,这是一个简单的PHP字符串文字/连接问题 第二个双引号以字符串文字结尾,PHP无法识别以下
SELECT…
$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的语句中多次使用相同的bind变量名(至少以前是这样)会出现问题,因为PDO实际上是将其从命名符号转换为位置符号的
我还向子查询添加了一个limit1
子句,因为如果返回多行,MySQL将抛出一个错误。(如果userid
在bank
表中是唯一的,则不会有什么区别。如果它不是唯一的,我们需要哪一行?最新的、goldbalance值最大的一行,等等。我们可以通过添加聚合或订单,使其更具确定性。)
如果一行没有返回,我们会得到一个空值,当我们添加一个空值时,我们会得到一个空值。我们是否要将缺少的行或空值处理为零
如果userid
在bank
表中是唯一的,我将使用join操作进行此查询。为了模拟子查询,我们需要一个外部连接,例如
由于没有一个标识符是保留字,我们不需要在标识符周围加上反标记
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
如果我们想模拟原始查询,我们需要从aboutb.goldbalance
中删除IFNULL
包装,这样它就可以返回NULL,因此ticketamount将设置为NULL
如果我们不想在相关行从银行“丢失”时更新该行,我们可以执行内部联接而不是外部联接(即删除LEFT
关键字)
您的表/列使用了错误的标识符限定符。在这里,添加
$conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_异常)代码>打开连接后,您将看到“更多”语法错误。不要在标识符周围使用单引号,请使用反勾号。(单引号用于字符串文字,而不是表名或列名。)此外,我没有看到$stmt->execute()
和$result
之间的任何链接。。。但是您不需要运行单独的语句来检查goldbalance
,当goldbalance为零时运行更新会更快,MySQL会发现该行实际上不需要更改。(如果我们希望goldbalance几乎总是为零,那么我会做单独的检查,也就是说,当运行更新时是例外,而不是规则。)如果您知道您将始终从银行中获得匹配行,则可以从更新语句中删除LEFT
关键字。使用LEFT关键字,如果在bank中找不到匹配的行,那么语句将添加NULL,这将导致NULL值,我怀疑您不想用NULL覆盖ticketamount的值。(如果您保留LEFT关键字,您需要在IFNULL函数中包装goldbalance,以获得一个零来代替NULL。)您好@spencer7593非常感谢您的回复!读了你的答案后,我意识到