Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Oracle从其他列计算结果更新列_Java_Database_Oracle_Prepared Statement - Fatal编程技术网

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不允许更改虚拟列的值。