我有一个带有unsigned int的数据库表,表示钱包余额。此列称为钱包。它位于一个名为users的表中。
以下查询通过mysql cli失败:
UPDATE users set wallet = `wallet` - 550000000 WHERE username = 'user'
显示错误消息:
ERROR 1690(22003):BIGINT UNSIGNED值超出范围 '(
database
。users
。wallet
- 550000000)'
问题是,当通过PDO使用ERRMODE_EXCEPTION执行时,它会将钱包余额设置为0并继续执行而不会在异常中引发上述错误
SELECT @@ sql_mode在代码和mysql cli中都不返回任何内容。
这是创建数据库句柄并将其返回给查询对象的函数
//This function connects to a database
public function connect($dbname,DBConfig $config = NULL)
{
//If the connection is already set return it
if(isset($this->dbs[$dbname]))
return $this->dbs[$dbname];
//If the config object is not already set, and still null, throw exception
if(!isset($this->_config[$dbname]))
{
if($config === NULL)
throw new PDOdatabasesException('Database configuration object is not set',1);
$this->_config[$dbname] = $config;
}
$config = $this->_config[$dbname];
//Create a PDO object
$this->dbs[$dbname] = new PDO(
$config::type .
':host=' . $config::$host .
';port=' . $config::$port .
';dbname=' . $dbname,
$config::$user,
$config::$password
);
//Tell the handle to throw exceptions
$this->dbs[$dbname]->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$this->dbs[$dbname]->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
//Return a reference to the newly created PDO object
return $this->dbs[$dbname];
} //End connect()
尝试省去粘贴一堆不必要的代码的需要..我的查询对象从上面获取数据库句柄,并准备并执行此语句:
'UPDATE users SET wallet = wallet - ? WHERE id = ?'
绑定金额(约1000万)和用户ID,然后执行。
电子钱包余额可以为0,查询仍会成功执行。为什么当cli不能发生这种情况?它没有意义!!
我相信我需要再次重申如果将钱包放到0以下,这个查询应该会失败!
它通过pdo成功,但不是通过mysql cli,我的问题是为什么?
答案 0 :(得分:1)
钱包的结果 - 550000000应小于0且您的列为UNSIGNED。尝试将列类型从BIGINT UNSIGNED更改为BIGINT
答案 1 :(得分:1)
这显然是PDO :: bindValue()和PDO :: bindParam()
编辑: 我显然很愚蠢,并没有意识到在将整数绑定到查询时需要定义data_type。
我已将代码简化为以下内容:
$db = new PDO('mysql:dbname=test;host=127.0.0.1','omitted','omitted');
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
try{
$statement = $db->prepare("UPDATE test set number = number - ? WHERE id = 1");
$statement->bindValue(1,1000000000);
$statement->execute();
}catch(PDOException $e)
{
die($e->getMessage());
}
将语句更改为(并且不使用bindValue或bindParam):
$statement = $db->prepare("UPDATE test set number = number - 100000000 WHERE id = 1");
然后代码抛出预期的异常
再次改为: $语句> bindValue(1,1000000000,PDO :: PARAM_INT);
按预期抛出