Java Oracle从其他列计算结果更新列
我有一个表Java Oracle从其他列计算结果更新列,java,database,oracle,prepared-statement,Java,Database,Oracle,Prepared Statement,我有一个表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),
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
支付
字段的值是通过将成人
和儿童
值相加来计算的。通过将婴儿
和船员
相加,我可以得到非付费
值。然后我可以将付费
和非付费
字段相加,得到乘客总数
问题是,当我更新成人
、儿童
、婴儿
和乘员
字段时,每个字段的值可能为空
,数据库是否可以重新计算付费
、非付费
和乘客总数
,而无需手动更新
我尝试了以下查询,结果出乎意料
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语句参数,它可能是NULL值。如何自动更新最后三个字段?您可以使用一个触发器,在更新发生后对乘客
表进行额外更新:
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;
要使用触发器,您只需像往常一样对乘客进行更新。如果您更新了<代码> >子<代码>、<代码>婴儿< /代码>或<代码>工作人员<代码>字段>对于给定记录,>代码> null >代码>,那么我的触发器将在代码总数中处理< <代码> null >代码> <代码> 0 >代码> < p>如果您使用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
*/
允许在NVL函数中传递一个参数吗?@感谢您指出这一点。不,这是不允许的,甚至没有任何意义^^我可以使用NVL(:NEW.field,:OLD.field)
,这意味着如果新值为null,则使用旧值吗?如果触发器
更新了相同的表,它是否会被重新执行?是的,您可以使用NVL(:NEW.field,:OLD.field)
,否,触发器不会生成另一个触发器(这将是无限的)。关于虚拟列的好信息。不幸的是,我正在使用的现有应用程序仍然使用10g。我可以手动更新虚拟列吗?AFAIK不允许更改虚拟列的值。