PDO事务更新使用来自不同表的另一行的值在一行上出错

时间:2015-06-01 00:34:02

标签: php mysql if-statement pdo

更新了当前的尝试代码

Hi_I我正在尝试对一个行值进行PDO检查,然后在一个表中的一行上使用来自我的数据库中不同表中的行的值,在事务中执行,但我保留得到错误。

我有两个表,它们是table1bank

table1包含useridticketamount列。

bank包含useridgoldbalance列。

ticketamountgoldbalance是INT。 这两行永远不会NULL,创建用户帐户时,0的值会输入到这些行中,因此总会有一个值。

userid是一个独特的列。

我想要做的是,运行一个PDO事务,通过添加ticketamount中存储的任何值来更新goldbalance,我试图通过将其设置为{{1}来执行此操作}}

这是我的完整代码:

ticketamount + (some code to fetch the goldbalance amount here)

如果bank.goldbalance = 0那么运行事务没有意义,所以我想先检查一下,如果它确实= 0那么我只想回显“0”,但是如果它=> 0那么我想要运行事务并在完成时回显“1”。

我正在尝试使事务获取bank.goldbalance中的值,然后将其添加到table1.ticketamount中的值。然后,事务的第二部分应将bank.goldbalance设置为“0”。

我现在使用上面的代码在控制台中获得的响应是​​:

  

“错误:SQLSTATE [42000]:语法错误或访问冲突:1064您的SQL语法出错;请查看与您的MySQL服务器版本对应的手册,以便在''bank'WHERE'附近使用正确的语法userid'='113234523347''在第1行“

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

关于这个问题的任何其他建议真的很棒, 提前谢谢!

1 个答案:

答案 0 :(得分:1)

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

然后,将变量传递给prepare

在这两者之间,您可以执行字符串变量的echovar_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的语句中多次使用相同的绑定变量名称时出现问题(至少曾经存在),因为PDO实际上将其转换为来自命名表示法的位置表示法。< / p>

我还在子查询中添加了一个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

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

如果我们不希望更新行,如果相关行从bank中“丢失”,我们可以执行内部联接而不是外部联接(即删除LEFT关键字。)