Php 防止mysql中的十进制值变为负值

Php 防止mysql中的十进制值变为负值,php,mysql,Php,Mysql,防止用户余额变为负值 (除了PHP端的检查之外)我在INSERT之前使用了以下Mysql触发器: BEGIN UPDATE `table` SET `user_balance` = user_balance - NEW.amount WHERE `uid` = NEW.id; -- Some other inserts etc... END 我认为这是一个插入前的触发器,它将阻止插入任何可能使余额为负数的新发票,但不会 即使STRICT(严格)模式处于打开状态,并且use

防止用户余额变为负值 (除了PHP端的检查之外)我在INSERT之前使用了以下
Mysql触发器:

BEGIN

    UPDATE `table` SET `user_balance` = user_balance - NEW.amount WHERE `uid` = NEW.id;

    -- Some other inserts etc...

END
我认为这是一个插入前的
触发器,它将阻止插入任何可能使余额为负数的新发票,但不会

即使STRICT(严格)模式处于打开状态,并且
user\u balance
列为
UNSIGED DECIMAL
,触发器也不会停止插入,如果为负,则该字段将简单地变为0

我尝试手动运行更新查询,但它会像预期的那样抛出一个错误,触发器的动作不一样

编辑: 有人知道为什么它可以在手动
更新
上正常工作,但不能在触发器上正常工作吗


在执行更新之前,必须检查减法的结果

 UPDATE `table` 
 SET `user_balance` = user_balance - NEW.amount 
 WHERE `uid` = NEW.id
   AND user_balance - NEW.amount >= 0
或者最好先获取值并引发错误:


代码的哪一部分让你认为这会检查负数?@JacobH如果数量超出范围,Mysql严格模式将阻止插入或更新,当我手动尝试更新查询时,它会按预期工作(抛出一个值超出范围的错误,如果结果为负数则不会执行)这似乎是一个相当糟糕的设计。为什么不能在插入之前检查平衡是否为负值?我会避免这种设计,并在应用层中完成所有工作。如果您决定在将来更改数据库,那么它就不会像您依赖mysql触发器时那样微不足道。@allinking我在PHP端进行了检查,正如我所提到的,但是我看到了在PHP端同时发生多个插入并且值为负值的罕见情况。(例如,两个脚本同时检查值是否正确,但随后它们都会更新,并且金额变为负值)谢谢,但这样无论如何都会插入发票,因为触发器将正常运行(不会影响任何行),不是吗?即使我删除触发器并在数据库事务中与发票一起运行此
更新
插入
,它仍然不算作失败,并且在更新未执行时执行插入。非常感谢,我不知道。。。在您的专业意见中,您认为触发器方法更好吗?还是我应该在PHP端的数据库事务中执行
UPDATE
INSERT
?我不确定您的情况如何。但是如果是一个用户界面,我不会将插入发送到db。我将首先收集db值,并在客户端验证该值。不管怎样,如果你在多用户环境中,你仍然需要触发器。在这种情况下,您可以取消转换并向用户报告。只是为了澄清。你可能两者都需要。您可以在客户端进行验证以改进用户界面,但也可以将其包含在数据库中以确保数据库的完整性。非常感谢您的解释。
 SET @user_balance := 0;
 SELECT @user_balance := `user_balance`
 FROM `table` 
 WHERE `uid` = NEW.id;

IF @user_balance - user_balance >= 0 THEN
     UPDATE `table` 
     SET `user_balance` = user_balance - NEW.amount 
     WHERE `uid` = NEW.id
       AND user_balance - NEW.amount >= 0
ELSE 
    set @msg = concat('MyTriggerError: Trying to insert a negative value in trigger: '
                     , cast(@user_balance - NEW.amount as varchar));
    signal sqlstate '45000' set message_text = @msg;
END IF;