MySQL неотрицательные столбцы INT - PullRequest
3 голосов
/ 07 января 2009

Я хочу сделать следующий запрос:

UPDATE `users` SET balance = (balance - 10) WHERE id=1

Но если баланс станет отрицательным, я хочу вернуть ошибку. Есть идеи, если это возможно?

Ответы [ 5 ]

5 голосов
/ 07 января 2009

Если вы делаете

UPDATE `users` SET balance = (balance - 10) WHERE id=1 and balance >=10

Вы должны быть в состоянии обнаружить, что строка не была изменена.

Обратите внимание, что хотя в другом ответе предлагается использовать столбец int без знака, это может не сработать:

Создать тестовую таблицу

create table foo(val int unsigned default '0');
insert into foo(val) values(5);

Теперь мы попытаемся вычесть 10 из нашей тестовой строки:

update foo set val=val-10;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

mysql> select * from foo;
+------------+
| val        |
+------------+
| 4294967295 |
+------------+

Это было в MySQL 5.0.38

4 голосов
/ 07 января 2009

Вы можете сделать поле баланса таблицы пользователей беззнаковым целым:

ALTER TABLE `users` CHANGE `balance` `balance` INT UNSIGNED;
1 голос
/ 07 января 2009

Подобные вещи выполняются триггерами . MySql поддерживает только триггеры начиная с 5.0.2.

DELIMITER $$
CREATE TRIGGER balance_check BEFORE INSERT ON user FOR EACH ROW
BEGIN
    IF new.balance < @limit_value THEN
        -- do something that causes error. 
        -- mysql doesn't have mechanism to block action by itself
    END IF;
END $$
DELIMITER ;

Триггеры в MySql довольно элементарны. Вы должны взломать вещи, чтобы сделать что-то (например, вызвать ошибку).

0 голосов
/ 15 февраля 2013

Просто совет, который не подходит в качестве комментария. Я просто пытался вычесть 32000 из 32047 (не отрицательный результат) и получал ошибки. Также сбивало с толку, я получал ошибки BIGINT, но мое вычитание было в столбце SMALLINT! (Что все еще не имеет смысла.)

Если вы получаете ошибки «вне диапазона», даже если ваш «баланс» положительный, попробуйте добавить «предел 1» в конец вашего запроса. Может быть, это ошибка в MySQL?

mysql> update posts set cat_id=cat_id-32000 where timestamp=1360870280;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`xxxxx`.`posts`.`cat_id` - 32000)'

mysql> update posts set cat_id=cat_id-32000 where timestamp=1360870280 limit 1; 
Query OK, 1 row affected (6.45 sec)
Rows matched: 1  Changed: 1  Warnings: 0

В моем случае отметка времени уникальна (я только что проверил, чтобы убедиться), но не была явно определена как уникальная при создании таблицы. Так почему же здесь необходим «предел 1»? Но кого это волнует, это работает!

0 голосов
/ 07 января 2009

Я не думаю, что вы можете сделать это с помощью простого запроса. Вы должны использовать пользовательскую функцию mysql, которая управляет этим перед обновлением строки. или триггер

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...