Saya tidak bisa mengatakan apa-apa tentang kinerja kueri, maaf. Tetapi Anda mungkin ingin mempertimbangkan pemicu untuk mencegah kasus 'new_balance' menjadi negatif. (Karena menurut saya aneh untuk melakukan penyisipan nol jika 'new_balance' lebih rendah dari $amount, tetapi mungkin berhasil :)).
Lihat dokumentasi MySQL 5.0 untuk detail cara membuat pemicu.
Pada dasarnya Anda akan memberi tanda centang, jika NEW.new_balance negatif ke pemicu SEBELUM. Jika ya, maka Anda akan menggunakan "STOP ACTION", kesalahan yang disengaja dalam eksekusi, untuk membatalkan pemicu dan kueri INSERT. Lihat ide di halaman yang disebutkan di komentar.
Pembaruan:Sedikit mengutak-atik (alasan saya untuk menginstal MySQL di rumah).
Versi saya memiliki masalah untuk menulis kedua kalinya ke DB untuk setiap nilai yang dimasukkan ke dalam moneylog.
Mungkin beralih ke proc yang tersimpan akan disarankan. Atau orang lain punya ide yang lebih baik, saya tidak terlalu suka 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;
Mungkin cocok untuk Anda, output saya untuk INSERT-Lines adalah:
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)