mysql - MySQL:在另一个表中由 INSERT 触发时计算值并设置
问题描述
快速介绍:我正在尝试制作一个程序,让我和我的朋友可以跟踪谁欠谁的钱。现在我正在处理数据库。我正在这个网站上测试它。
CREATE TABLE `payments`
(
`payment_id` integer NOT NULL AUTO_INCREMENT ,
`title` varchar(200) NOT NULL ,
`descrp` tinytext NULL ,
`room_id` integer NOT NULL ,
`u_from` integer NOT NULL ,
`u_to` integer NOT NULL ,
`value` decimal DEFAULT 0, CHECK (value>=0),
PRIMARY KEY (`payment_id`),
KEY `fkIdx_39` (`u_from`),
CONSTRAINT `FK_38` FOREIGN KEY `fkIdx_39` (`u_from`) REFERENCES `users` (`user_id`),
KEY `fkIdx_42` (`u_to`),
CONSTRAINT `FK_41` FOREIGN KEY `fkIdx_42` (`u_to`) REFERENCES `users` (`user_id`),
KEY `fkIdx_51` (`room_id`),
CONSTRAINT `FK_50` FOREIGN KEY `fkIdx_51` (`room_id`) REFERENCES `rooms` (`room_id`)
);
CREATE TABLE `rooms`
(
`room_id` integer NOT NULL AUTO_INCREMENT ,
`web_link` varchar(30) NOT NULL ,
`name` varchar(200) NOT NULL ,
`descrp` tinytext,
PRIMARY KEY (`room_id`)
);
CREATE TABLE `user_room`
(
`id` integer NOT NULL AUTO_INCREMENT ,
`user_id` integer NOT NULL ,
`room_id` integer NOT NULL ,
`user_role` varchar(200) DEFAULT "standard" ,
`cash` decimal NOT NULL DEFAULT 0 ,
PRIMARY KEY (`id`),
KEY `fkIdx_16` (`user_id`),
CONSTRAINT `FK_15` FOREIGN KEY `fkIdx_16` (`user_id`) REFERENCES `users` (`user_id`),
KEY `fkIdx_36` (`room_id`),
CONSTRAINT `FK_35` FOREIGN KEY `fkIdx_36` (`room_id`) REFERENCES `rooms` (`room_id`)
);
CREATE TABLE `users`
(
`user_id` integer NOT NULL AUTO_INCREMENT ,
`login` varchar(50) NOT NULL ,
`display_name` varchar(100) NULL ,
PRIMARY KEY (`user_id`)
);
DELIMITER //
CREATE TRIGGER after_new_payment_sum_cash
AFTER INSERT ON payments FOR EACH ROW
BEGIN
DECLARE user_from_cash decimal;
DECLARE user_to_cash decimal;
SET @user_from_cash := (SELECT cash FROM user_room WHERE user_id = NEW.u_from);
SET @user_to_cash := (SELECT cash FROM user_room WHERE user_id = NEW.u_to);
UPDATE user_room SET cash = (user_from_cash - NEW.value) WHERE user_id = NEW.u_from;
UPDATE user_room SET cash = (user_to_cash + NEW.value) WHERE user_id = NEW.u_to;
END //
DELIMITER ;
INSERT INTO users (login, display_name) VALUES ("kacper1", "Kacper2");
INSERT INTO users (login, display_name) VALUES ("kacper2", "Kacper2");
INSERT INTO rooms (web_link, name, descrp) VALUES ('xx', 'room1', 'description');
INSERT INTO user_room (user_id, room_id) VALUES ((SELECT user_id FROM users WHERE login='kacper1'),
(SELECT room_id FROM rooms WHERE name ='room1'));
INSERT INTO user_room (user_id, room_id) VALUES ((SELECT user_id FROM users WHERE login='kacper2'),
(SELECT room_id FROM rooms WHERE name ='room1'));
select * from users;
select * from rooms;
select * from user_room;
select * from payments;
INSERT INTO payments (title, descrp, room_id, u_from, u_to, value) VALUES ('plat1', 'plat1 desc', 1, 1, 2, 10);
select * from user_room;
正如您自己看到的那样,我得到了这个错误:ERROR 1048 (23000) at line 88: Column 'cash' cannot be null
触发器的目的是计算表cash
中的字段并保持它不断更新。
据我了解,其中一条是给出此错误。user_room
user_from
user_to
SET...
解决方案
公式user_from_cash - NEW.value
变为NULL
应有的样子@user_from_cash
。
进一步改进:
- 你最好在触发器中使用局部变量(不是@var)
DECIMAL
-datatype 应该定义长度。
推荐阅读
- python - 如何以科学计数法获取 Chart js 标签
- javascript - 我如何创建一个可以接收和发送邮件到 Zimbra 服务器的模块
- c# - 从 ASP.NET Core 中的 PipeReader 读取时,如何正确处理所有边缘情况?
- json - 我应该如何构建这个嵌套的 JSON 数据库以导入到 firebase firestore?
- python-3.x - 单元测试模拟补丁没有为方法创建模拟
- dataweave - 如何在 XML 有效负载中用 & 替换 &
- terraform - 如何使用 terragrunt 作为预处理器并生成 terraform 文件
- ssl-certificate - 如何在 ubuntu 上使用虚拟 IP 地址安装 SSL 证书,而无需域名仅使用虚拟 IP 地址?
- okhttp - okhttp 对请求正文的大小有任何限制吗?
- java - 如何在java中访问类数组变量?