我有一个表passenger
,结构如下。
CREATE TABLE passenger (
id NUMERIC(12,0) NOT NULL,
station VARCHAR(3),
adult NUMERIC(3,0),
child NUMERIC(3,0),
infant NUMERIC(3,0),
crew NUMERIC(3,0) DEFAULT 0,
paying NUMERIC(4,0),
non_paying NUMERIC(4,0),
total_passenger NUMERIC(3,0),
PRIMARY KEY (id)
);
初步记录如下。
id | station | adult | child | infant | crew | paying | non_paying | total_passenger
100 | GWN | 20 | 4 | 1 | 2 | 24 | 3 | 27
paying
字段的值是通过对adult
和child
值求和来计算的。并且,通过对infant
和crew
求和,我可以获得non_paying
值。然后,我可以将paying
和non_paying
字段相加以获得total_passenger
。
问题是,当我更新adult
,child
,infant
和crew
字段时,每个字段的值可能为NULL
,数据库重新计算paying
,non_paying
和total_passenger
,而无需手动更新它们?
我尝试了以下查询,但结果出乎意料。
UPDATE passenger
SET adult = NVL(NULL, adult),
child = NVL(6, child),
infant = NVL(3, infant),
crew = NVL(NULL, crew),
paying = adult + child,
non_paying = infant + crew,
total_passenger = paying + non_paying
WHERE id = 100;
NULL
关键字来自预准备语句参数,该参数可能为null。如何自动更新最后三个字段?
答案 0 :(得分:1)
您可以使用触发器在passenger
发生后对UPDATE
表执行额外更新:
CREATE OR REPLACE TRIGGER update_passenger
AFTER UPDATE OF passenger
FOR EACH ROW
BEGIN
UPDATE passenger
SET
paying = NVL(:NEW.adult, 0) + NVL(:NEW.child, 0),
non_paying = NVL(:NEW.infant, 0) + NVL(:NEW.crew, 0),
total_passenger = NVL(:NEW.adult, 0) + NVL(:NEW.child, 0) +
NVL(:NEW.infant, 0) + NVL(:NEW.crew, 0)
END;
要使用触发器,您只需像往常一样对passenger
进行更新。如果您确实为给定记录更新了adult
,child
,infant
或crew
字段到NULL
,那么我的触发器会处理{{1在总计的计算中作为NULL
。
答案 1 :(得分:0)
如果您使用上面的oracle 11g,请考虑使用虚拟列。
create table passenger(id numeric(12, 0) not null,
station varchar2(3),
adult numeric(3, 0) default 0,
child numeric(3, 0) default 0,
infant numeric(3, 0) default 0,
crew numeric(3, 0) default 0,
paying numeric(4, 0) generated always
as(adult + child) virtual,
non_paying numeric(4, 0) generated always
as(infant + crew) virtual,
total_passenger NUMERIC(3, 0) generated always
as(adult + child + infant + crew) virtual,
primary key(id));
insert into passenger
(id, station, adult, child, infant, crew)
values
(1, '1', 2, 3, 4, 5);
insert into passenger (id, station, child, crew) values (2, '2', 7, 8);
select * from passenger;
/*
ID STATION ADULT CHILD INFANT CREW PAYING NON_PAYING TOTAL_PASSENGER
1 1 2 3 4 5 5 9 14
2 2 0 7 0 8 7 8 15
*/