Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Cách tốt nhất để ngăn giá trị âm trong mysql

Tôi không thể nói bất cứ điều gì về hiệu suất của truy vấn, xin lỗi. Nhưng bạn có thể muốn xem xét các trình kích hoạt để ngăn trường hợp 'new_balance' trở nên tiêu cực. (Bởi vì tôi thấy kỳ lạ khi thực hiện chèn null trong trường hợp 'new_balance' thấp hơn số tiền $, nhưng nó vẫn có thể hoạt động :)).

Xem tài liệu của MySQL 5.0 để biết chi tiết cách tạo trình kích hoạt.

Về cơ bản, bạn sẽ kiểm tra, nếu NEW.new_balance âm thành một BEFORE-trigger. Nếu có, thì bạn sẽ sử dụng "STOP ACTION", một lỗi cố ý trong quá trình thực thi, để hủy bỏ truy vấn kích hoạt và CHÈN. Xem các ý tưởng trên trang được đề cập trong phần bình luận.

Cập nhật:Tinkered một chút xung quanh (lý do của tôi để cài đặt MySQL ở nhà).

Phiên bản của tôi gặp sự cố khi ghi lần thứ hai vào DB cho mỗi giá trị được nhập vào moneylog.

Có lẽ nên chuyển sang một proc được lưu trữ. Hoặc ai đó có ý tưởng hay hơn, tôi không thích DB lắm đâu :)

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;

Có thể nó sẽ phù hợp với bạn, đầu ra của tôi cho INSERT-Lines là:

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. tìm kiếm một phần từ mysql

  2. Node.js và mysql Callback:truy vấn trong cuộc gọi lại truy vấn

  3. MySQL LIMIT trong một truy vấn con tương ứng

  4. thứ tự theo .... số? Giúp tôi sắp xếp địa chỉ ip

  5. Laravel:Kết quả kết hợp truy vấn lồng vào một mảng con