在 PHP 和 MySQLi 的预处理语句中使用相同的值两次

Posted

技术标签:

【中文标题】在 PHP 和 MySQLi 的预处理语句中使用相同的值两次【英文标题】:Using the same value twice in a prepared statement with PHP and MySQLi 【发布时间】:2020-12-24 09:36:26 【问题描述】:

如何启动用户定义变量并在 php/mysqli 连接上准备的单个 MySQL 语句中使用它两次?

我有一个带有购物车的应用程序,用户可以在其中将信用添加到他们的帐户中,并且数据库中有两个字段携带此值:credit_balance 和 credit_available。我将信用分为两个字段,因为用户可以搁置(南非术语,用于支付押金以确保以后购买的物品)并且在待定期间,将资金留作搁置-并且不能在其他地方使用。

所以,当用户向他们的帐户添加信用时,我想更新这两个字段,这就是我想出的:

if($update = $mysqli->prepare("UPDATE user SET credit_balance = credit_balance + @new_credit, credit_available = credit_available + @new_credit WHERE user_id = ? AND @new_credit = ?") 
  $update->bind_param("ii", $user_id, $deposit);
  $update->execute();
  $update->close();

代替:

if($update = $mysqli->prepare("UPDATE user SET credit_balance = credit_balance + ?, credit_available = credit_available + ? WHERE user_id = ?") 
  $update->bind_param("iii", $deposit, $deposit, $user_id);
  $update->execute();
  $update->close();

像我一样做这件事有什么影响,这是一个可靠的解决方案吗?它在我的本地机器上运行,我担心在不同机器/环境上的兼容性。

【问题讨论】:

虽然看起来更整洁,但第二种方法更清晰(恕我直言)。也不确定您的第一条语句是如何工作的,因为您的 SQL 中有 user_id = 1 我认为第一个行不通。 mysql 从上到下 and ,因此 ypu 只能使用用户定义的变量,这些变量之前已经声明过 @NigelRen 我在那里犯了一个错误。 “1”的意思是“?”。无论如何,我已经检查了 MySQL 文档,但我找不到任何部分说明第一种方法是否可能不适用于某些版本的 MySQL,这就是我关心的地方。我想我将不得不坚持第二种方法。 @nbk 我测试了第一种方法,它可以在我的本地机器上运行,也可以在运行 MySQL 5.7.3 的 Amazon Linux AMI 实例上运行。 不,不是dbfiddle.uk/… 【参考方案1】:

如果 mysqli 支持命名参数,这将很容易 - 但不幸的是它不支持。您可能会考虑更改为实现此功能的 PDO。

从 SQL 的角度来看:用户变量在 MySQL 中很棘手,并计划弃用。我认为最安全的方法是select子查询中的参数,然后将其与目标表连接:

UPDATE user u
INNER JOIN (SELECT ? user_id, ? new_credit) p
    ON p.user_id = u.user_id
SET 
    u.credit_balance   = u.credit_balance   + p.new_credit, 
    u.credit_available = u.credit_available + p.new_credit

【讨论】:

能否与PDO重用同名参数取决于PDO::ATTR_EMULATE_PREPARES是否为TRUE。 这看起来更干净。回到我的工作站并提出建议后,我会尽快尝试。

以上是关于在 PHP 和 MySQLi 的预处理语句中使用相同的值两次的主要内容,如果未能解决你的问题,请参考以下文章

PHP中的MySQLi扩展学习mysqli的事务与预处理语句

PHP中的MySQLi扩展学习MySQLI_STMT对象操作

PHP MYSQLI中事务处理

php mysqli扩展之预处理

PHP 使用 Mysqli 的 prepare 语句有啥好处?

什么时候在 PHP Mysqli 中使用准备好的语句? - 用户表单搜索输入与选择查询