Mysql
 sql >> база данни >  >> RDS >> Mysql

Най-добрият начин за предотвратяване на отрицателна стойност в mysql

Не мога да кажа нищо за изпълнението на заявката, съжалявам. Но може да искате да помислите за тригери, за да предотвратите превръщането на 'new_balance' в отрицателен случай. (Защото ми се струва странно да правя нулева вмъкване в случай, че 'new_balance' е по-нисък от $amount, но въпреки това може да работи :) ).

Вижте документацията на MySQL 5.0 за подробности как да създадете тригер.

По принцип вие бихте поставили чека, ако NEW.new_balance е отрицателен в тригер BEFORE. Ако отговорът е да, тогава ще използвате "STOP ACTION", умишлена грешка в изпълнението, за да прекратите задействането и INSERT-заявката. Вижте идеи на споменатата страница в коментарите.

Актуализация:Поправих малко (моето извинение за инсталирането на MySQL у дома).

Моята версия има проблем с записването за втори път в DB за всяка стойност, въведена в moneylog.

Може би е препоръчително преминаването към съхранена процедура. Или някой друг има по-добра идея, аз не съм много по DB :)

CREATE DATABASE triggertest;
CONNECT triggertest;

CREATE TABLE transferlog (
  account SMALLINT UNSIGNED NOT NULL ,
  amount INT NOT NULL,
  new_balance INT NOT NULL
) ENGINE=INNODB;

CREATE TABLE stopaction (
  entry CHAR(20) NOT NULL,
  dummy SMALLINT,
  UNIQUE(`entry`)
);

INSERT INTO stopaction (`entry`) VALUES ('stop');

DELIMITER #
CREATE TRIGGER nonneg_insert BEFORE INSERT ON transferlog
  FOR EACH ROW BEGIN
    INSERT INTO stopaction (`entry`)
      SELECT CASE WHEN NEW.new_balance<0 THEN 'stop'
                  ELSE 'none' END;
    DELETE FROM stopaction WHERE entry!='stop';
  END;
#

CREATE TRIGGER nonneg_update BEFORE UPDATE ON transferlog
  FOR EACH ROW BEGIN
    INSERT INTO stopaction (`entry`)
      SELECT CASE WHEN NEW.new_balance<0 THEN 'stop'
                  ELSE 'none' END;
    DELETE FROM stopaction WHERE entry!='stop';
  END;
#
DELIMITER ;


INSERT INTO transferlog (`account`, `amount`, `new_balance`)  
  VALUES (1, 1000, 1000);
INSERT INTO transferlog (`account`, `amount`, `new_balance`)
  VALUES (1, -1000, 0);
INSERT INTO transferlog (`account`, `amount`, `new_balance`)
  VALUES (1, -1000, -1000);
INSERT INTO transferlog (`account`, `amount`, `new_balance`)
  VALUES (1, 10, 20);
SELECT version();

DROP DATABASE triggertest;

Може би ще ви подхожда, моят изход за INSERT-Lines е:

mysql> INSERT INTO transferlog (`account`, `amount`, `new_balance`)  VALUES (1, 1000, 1000);
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO transferlog (`account`, `amount`, `new_balance`)  VALUES (1, -1000, 0);
Query OK, 1 row affected (0.02 sec)

mysql> INSERT INTO transferlog (`account`, `amount`, `new_balance`)  VALUES (1, -1000, -1000);
ERROR 1062 (23000): Duplicate entry 'stop' for key 1

mysql> INSERT INTO transferlog (`account`, `amount`, `new_balance`)  VALUES (1, 10, 20);
Query OK, 1 row affected (0.02 sec)

mysql> SELECT version();
+---------------------+
| version()           |
+---------------------+
| 5.0.67-community-nt |
+---------------------+
1 row in set (0.00 sec)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Създаване на сайт за видео споделяне, трябва видео плейър

  2. ПОРЪЧАЙТЕ ПО един идентификатор, когато има повече от същите идентификатори в една таблица

  3. Интерполирайте липсващите стойности в MySQL таблица

  4. Мокнете MySQL база данни в Python

  5. Escape име на таблицата MySQL