我已创建此触发器以更新发票金额。这是保存触发器的付款表。
ci_payments
CREATE TABLE `ci_payments` (
`payment_id` bigint(10) NOT NULL AUTO_INCREMENT,
`customer_id` bigint(10) NOT NULL,
`payment_method` varchar(15) NOT NULL,
`receipt_number` varchar(50) NOT NULL,
`cheque_number` varchar(50) NOT NULL,
`amount` decimal(18,2) NOT NULL,
`payment_on` datetime NOT NULL,
`payment_note` mediumtext NOT NULL,
`current_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`payment_id`), KEY `invoice_id` (`customer_id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
这是Inovice表和数据:
例如,请将Customer ID: 8
的两张发票设为paid_amount 0.00
;
我试图通过付款表上的触发器更新发票金额。
假设客户已付400.00
,因此我想将第一张发票更新为paid
,将partial
更新为paid_amount
;
这是我创建的触发器
DELIMITER $$
CREATE TRIGGER uni_payment_updater AFTER INSERT ON ci_payments FOR EACH ROW BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE amt_diff, t_amount DECIMAL(9,2);
DECLARE inv_id INTEGER;
DECLARE cur CURSOR FOR select total_amount, invoice_id from ci_invoices where customer_id = new.customer_id and (status = "unpaid" or status = "partial") order by invoice_id asc;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET @uni_paid_amount := NEW.amount;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO t_amount, inv_id;
IF done THEN
LEAVE ins_loop;
END IF;
SET amt_diff = NEW.amount - t_total;
IF amt_diff > 0.00 THEN
UPDATE ci_invoices set paid_amount = amt_diff where invoice_id = inv_id;
END IF;
END LOOP;
CLOSE cur;
END;
$$
DELIMITER ;
但是我收到了这个错误
Unknown column 'uni_paid_amount' in 'field list'
任何人都可以帮助纠正我在哪里以及我做错了什么?
答案 0 :(得分:2)
<强>更新强>
修正查询:
set @paid = 200;
update invoice i
set
i.paid_amount = if(@paid <= total_amount, @paid, total_amount),
i.status = case when paid_amount = 0 then 'unpaid' when total_amount = paid_amount then 'paid' when paid_amount > 0 and paid_amount < total_amount then 'partial' else 'wtf' end,
i.id = if(@paid := if(@paid <= total_amount, 0, @paid - total_amount), i.id, i.id)
where i.customer_id = 16
order by id /*or whatever columns determines the order of the invoices*/
;
尝试以下操作,现在可以使用了:
mysql> drop table if exists invoice;
Query OK, 0 rows affected (0.00 sec)
mysql> create table invoice (
-> id int auto_increment primary key,
-> customer_id int,
-> total_amount decimal(10,2),
-> paid_amount decimal(10,2) default 0,
-> status varchar(50) default 'unpaid'
-> );
Query OK, 0 rows affected (0.06 sec)
mysql>
mysql> insert into invoice (customer_id, total_amount) values
-> (3, 0),
-> (8, 303.75),
-> (8, 200.00),
-> (16, 303.75),
-> (16, 200.00);
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql>
mysql> select * from invoice;
+----+-------------+--------------+-------------+--------+
| id | customer_id | total_amount | paid_amount | status |
+----+-------------+--------------+-------------+--------+
| 1 | 3 | 0.00 | 0.00 | unpaid |
| 2 | 8 | 303.75 | 0.00 | unpaid |
| 3 | 8 | 200.00 | 0.00 | unpaid |
| 4 | 16 | 303.75 | 0.00 | unpaid |
| 5 | 16 | 200.00 | 0.00 | unpaid |
+----+-------------+--------------+-------------+--------+
5 rows in set (0.01 sec)
mysql>
mysql>
mysql> set @paid = 400;
Query OK, 0 rows affected (0.00 sec)
mysql> update invoice i
-> set
-> i.paid_amount = if(@paid <= total_amount, @paid, total_amount),
-> i.status = case when paid_amount = 0 then 'unpaid' when total_amount = paid_amount then 'paid' when paid_amount > 0 and paid_amount < total_amount then 'partial' else 'wtf' end,
-> i.id = if(@paid := if(@paid <= total_amount, 0, @paid - total_amount), i.id, i.id)
-> where i.customer_id = 8
-> order by id /*or whatever columns determines the order of the invoices*/
-> ;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql>
mysql> select * from invoice;
+----+-------------+--------------+-------------+---------+
| id | customer_id | total_amount | paid_amount | status |
+----+-------------+--------------+-------------+---------+
| 1 | 3 | 0.00 | 0.00 | unpaid |
| 2 | 8 | 303.75 | 303.75 | paid |
| 3 | 8 | 200.00 | 96.25 | partial |
| 4 | 16 | 303.75 | 0.00 | unpaid |
| 5 | 16 | 200.00 | 0.00 | unpaid |
+----+-------------+--------------+-------------+---------+
5 rows in set (0.00 sec)
mysql>
mysql> set @paid = 200;
Query OK, 0 rows affected (0.00 sec)
mysql> update invoice i
-> set
-> i.paid_amount = if(@paid <= total_amount, @paid, total_amount),
-> i.status = case when paid_amount = 0 then 'unpaid' when total_amount = paid_amount then 'paid' when paid_amount > 0 and paid_amount < total_amount then 'partial' else 'wtf' end,
-> i.id = if(@paid := if(@paid <= total_amount, 0, @paid - total_amount), i.id, i.id)
-> where i.customer_id = 16
-> order by id /*or whatever columns determines the order of the invoices*/
-> ;
Query OK, 1 row affected (0.00 sec)
Rows matched: 2 Changed: 1 Warnings: 0
mysql>
mysql> select * from invoice;
+----+-------------+--------------+-------------+---------+
| id | customer_id | total_amount | paid_amount | status |
+----+-------------+--------------+-------------+---------+
| 1 | 3 | 0.00 | 0.00 | unpaid |
| 2 | 8 | 303.75 | 303.75 | paid |
| 3 | 8 | 200.00 | 96.25 | partial |
| 4 | 16 | 303.75 | 200.00 | partial |
| 5 | 16 | 200.00 | 0.00 | unpaid |
+----+-------------+--------------+-------------+---------+
5 rows in set (0.00 sec)
原始回答:
你根本不需要触发器,更不用说光标了(我总是试图不惜一切代价避免使用它)。您知道刚刚插入付款表的customer_id。然后在插入后触发此更新语句。
/*table serving as example*/
drop table if exists invoice;
create table invoice (
id int auto_increment primary key,
customer_id int,
total_amount decimal(10,2),
paid_amount decimal(10,2) default 0,
status varchar(50) default 'unpaid'
);
/*sample data*/
insert into invoice (customer_id, total_amount) values
(3, 0),
(8, 303.75),
(8, 200.00);
select * from invoice;
+----+-------------+--------------+-------------+--------+
| id | customer_id | total_amount | paid_amount | status |
+----+-------------+--------------+-------------+--------+
| 1 | 3 | 0.00 | 0.00 | unpaid |
| 2 | 8 | 303.75 | 0.00 | unpaid |
| 3 | 8 | 200.00 | 0.00 | unpaid |
+----+-------------+--------------+-------------+--------+
set @paid = 400;
update invoice i
set
i.paid_amount = if(@paid - total_amount >= 0, total_amount, total_amount - @paid),
i.status = if(@paid - total_amount >= 0, 'paid', 'partial'),
i.id = if(@paid := @paid - total_amount, i.id, i.id)
where i.customer_id = 8
order by id /*or whatever columns determines the order of the invoices*/
;
select * from invoice;
+----+-------------+--------------+-------------+---------+
| id | customer_id | total_amount | paid_amount | status |
+----+-------------+--------------+-------------+---------+
| 1 | 3 | 0.00 | 0.00 | unpaid |
| 2 | 8 | 303.75 | 303.75 | paid |
| 3 | 8 | 200.00 | 103.75 | partial |
+----+-------------+--------------+-------------+---------+
如果您坚持使用触发器,这里的触发器示例与此相同:
drop table if exists invoice;
create table invoice (
id int auto_increment primary key,
customer_id int,
total_amount decimal(10,2),
paid_amount decimal(10,2) default 0,
status varchar(50) default 'unpaid'
);
insert into invoice (customer_id, total_amount) values
(3, 0),
(8, 303.75),
(8, 200.00);
drop table if exists payment;
create table payment (
id int auto_increment primary key,
customer_id int,
amount decimal(10,2)
);
delimiter $$
create trigger pay after insert on payment for each row
begin
set @paid = new.amount;
update invoice i
set
i.paid_amount = if(@paid - total_amount >= 0, total_amount, total_amount - @paid),
i.status = if(@paid - total_amount >= 0, 'paid', 'partial'),
i.id = if(@paid := @paid - total_amount, i.id, i.id)
where i.customer_id = new.customer_id
order by id;
end $$
delimiter ;
select * from invoice;
+----+-------------+--------------+-------------+--------+
| id | customer_id | total_amount | paid_amount | status |
+----+-------------+--------------+-------------+--------+
| 1 | 3 | 0.00 | 0.00 | unpaid |
| 2 | 8 | 303.75 | 0.00 | unpaid |
| 3 | 8 | 200.00 | 0.00 | unpaid |
+----+-------------+--------------+-------------+--------+
insert into payment (customer_id, amount) values (8, 400);
select * from invoice;
+----+-------------+--------------+-------------+---------+
| id | customer_id | total_amount | paid_amount | status |
+----+-------------+--------------+-------------+---------+
| 1 | 3 | 0.00 | 0.00 | unpaid |
| 2 | 8 | 303.75 | 303.75 | paid |
| 3 | 8 | 200.00 | 103.75 | partial |
+----+-------------+--------------+-------------+---------+
请记住,应用程序逻辑在应用程序代码中更容易处理和维护,而不是在数据库触发器中。