sql >> Databáze >  >> RDS >> Mysql

Nejlepší způsob, jak zabránit záporné hodnotě v mysql

Nemohu říci nic o výkonu dotazu, omlouvám se. Možná však budete chtít zvážit spouštěče, abyste zabránili tomu, aby se případ 'new_balance' stal negativním. (Protože mi připadá zvláštní dělat null-insert v případě, že 'new_balance' je nižší než $amount, ale přesto by to mohlo fungovat :) ).

Viz dokumentace k MySQL 5.0 podrobnosti o vytvoření spouštěče.

V zásadě byste zaškrtli, zda je NEW.new_balance záporné, do spouštěče BEFORE. Pokud ano, pak byste použili "STOP ACTION", úmyslnou chybu při provádění, k přerušení spouštěče a dotazu INSERT. Podívejte se na nápady na zmíněné stránce v komentářích.

Aktualizace:Trochu jsem se pokoušel (moje výmluva pro instalaci MySQL doma).

Moje verze má problém zapsat podruhé do DB pro každou hodnotu zadanou do moneylogu.

Možná by bylo vhodné přejít na uložený proces. Nebo má někdo lepší nápad, já na DB tolik nejsem :)

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;

Možná se vám to bude hodit, můj výstup pro INSERT-Lines je:

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. SQL FLOAT:3 body, které vám pomohou vyhnout se podivným matematickým chybám

  2. Vyberte příspěvek, který nemá konkrétní štítek

  3. CREATE TABLE MySQL vs T-SQL s příklady syntaxe

  4. MySQL Create Table jako SELECT