其他列计算结果中的Oracle Update列

时间:2016-01-07 04:25:44

标签: 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),  
  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字段的值是通过对adultchild值求和来计算的。并且,通过对infantcrew求和,我可以获得non_paying值。然后,我可以将payingnon_paying字段相加以获得total_passenger

问题是,当我更新adultchildinfantcrew字段时,每个字段的值可能为NULL,数据库重新计算payingnon_payingtotal_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。如何自动更新最后三个字段?

2 个答案:

答案 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进行更新。如果您确实为给定记录更新了adultchildinfantcrew字段到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
*/