Oracle 从其他列计算结果中更新列
Oracle Update Column From Other Column Calculation Result
我有一个 table 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
.
问题是,当我用每个字段可能的 NULL
值更新 adult
、child
、infant
和 crew
字段时,数据库可以重新计算 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
关键字来自prepared statement参数,可能为null值。如何自动更新最后三个字段?
您可以使用触发器在 UPDATE
发生后对 passenger
table 进行额外更新:
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
,那么我的触发器将处理 NULL
作为 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
*/
我有一个 table 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
.
问题是,当我用每个字段可能的 NULL
值更新 adult
、child
、infant
和 crew
字段时,数据库可以重新计算 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
关键字来自prepared statement参数,可能为null值。如何自动更新最后三个字段?
您可以使用触发器在 UPDATE
发生后对 passenger
table 进行额外更新:
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
,那么我的触发器将处理 NULL
作为 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
*/