一个有关 decrement 和 increment 的问题

先说一下问题出现的场景

我是用的数据库是mysql, 表里面有一个虚拟币的字段, 某些情况下需要去减这个字段, 我都是使用 decrementdecrement 这两个方法取操作的, 数据库对这个字段设置的是 无符号, 也就是大于0的

XxModel::where(xxx)->decrement('sum', 20); //是这么操作的

一般情况下是正常的, 但是今天的情况是, 我的账户虚拟币 还有20个, 但是我代码减去100

XxModel::where(xxx)->decrement('sum', 100);

问题就出现了, 这个代码返回的值是1, 数据库字段值变成0, 这是什么情况?

后来我又尝试了以下的方法, 但是得到的结果都一致

DB::table('xxx')->where(xxx)->decrement('sum', 100);
DB::table('xxx')->where(xxx)->update(['sum' =>  DB::raw('sum - 100')]);
XxModel::where(xxx)->first()->decrement('sum', 100);

我在数据库执行

update table set sum = sum - 100 where xxx

会出现报错信息

Out of range value for column 'sum' at row 123016, Time: 0.089000s

所以laravel 的 decrement 是怎么算的呢

ruke
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

decrement执行的是update,返回的是执行成功是受影响的行数,而不是最后的结果。
在你你使用:update table set sum = sum - 100 where xxx会出现:BIGINT UNSIGNED value is out of range in的错误信息,这个错误信息和实际的意义是一样的。
但是你执行:update table set sum = -80 where xxx时是可以执行成功的。执行结果就是0,这可能是mysql机制问题。
decrement使用Update

        $wrapped = $this->grammar->wrap($column);
        $columns = array_merge([$column => $this->raw("$wrapped - $amount")], $extra);
        return $this->update($columns);

1、提前判断是剩余的数量是否够扣除。
2、可以使用原生sql
3、建议在数据库中,这个值最好不要设置成无符号型字段,应该可以为负数,你可以理解成用户透支,也可以做到出与入的统一。

4年前 评论
讨论数量: 3

返回的是受影响的行数吧

4年前 评论
Epona

unsigned 最小值是0, 无法变成负数的。

4年前 评论

decrement执行的是update,返回的是执行成功是受影响的行数,而不是最后的结果。
在你你使用:update table set sum = sum - 100 where xxx会出现:BIGINT UNSIGNED value is out of range in的错误信息,这个错误信息和实际的意义是一样的。
但是你执行:update table set sum = -80 where xxx时是可以执行成功的。执行结果就是0,这可能是mysql机制问题。
decrement使用Update

        $wrapped = $this->grammar->wrap($column);
        $columns = array_merge([$column => $this->raw("$wrapped - $amount")], $extra);
        return $this->update($columns);

1、提前判断是剩余的数量是否够扣除。
2、可以使用原生sql
3、建议在数据库中,这个值最好不要设置成无符号型字段,应该可以为负数,你可以理解成用户透支,也可以做到出与入的统一。

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!