我正在尝试在Oracle 10gR2中执行以下更新:
update
(select voyage_port_id, voyage_id, arrival_date, port_seq,
row_number() over (partition by voyage_id order by arrival_date) as new_seq
from voyage_port) t
set t.port_seq = t.new_seq
Voyage_port_id是主键,voyage_id是外键。我正在尝试根据每次航行中的日期分配一个序列号。
但是,上述情况因 ORA-01732而失败:数据操作操作在此视图中不合法
问题是什么?如何避免?
答案 0 :(得分:5)
由于您无法使用row_number
更新子查询,因此您必须计算更新的set
部分中的行号。起初我试过这个:
update voyage_port a
set a.port_seq = (
select
row_number() over (partition by voyage_id order by arrival_date)
from voyage_port b
where b.voyage_port_id = a.voyage_port_id
)
但这不起作用,因为子查询只选择一行,然后row_number()
始终为1.使用另一个子查询可以得到有意义的结果:
update voyage_port a
set a.port_seq = (
select c.rn
from (
select
voyage_port_id
, row_number() over (partition by voyage_id
order by arrival_date) as rn
from voyage_port b
) c
where c.voyage_port_id = a.voyage_port_id
)
它有效,但比我对这项任务的期望更复杂。
答案 1 :(得分:2)
您可以更新某些视图,但有一些限制,一个是视图不能包含分析函数。请参阅SQL Language Reference on UPDATE并搜索“analytic”的首次出现。
如果在同一天没有航行访问多个端口(或者日期包含使其唯一的时间组件),这将有效:
update voyage_port vp
set vp.port_seq =
( select count(*)
from voyage_port vp2
where vp2.voyage_id = vp.voyage_id
and vp2.arrival_date <= vp.arrival_date
)
我认为这可以处理一个航程每天访问超过1个端口并且没有时间组件的情况(尽管在同一天访问的端口序列是任意的):
update voyage_port vp
set vp.port_seq =
( select count(*)
from voyage_port vp2
where vp2.voyage_id = vp.voyage_id
and (vp2.arrival_date <= vp.arrival_date)
or ( vp2.arrival_date = vp.arrival_date
and vp2.voyage_port_id <= vp.voyage_port_id
)
)
答案 2 :(得分:-1)
不要认为你可以更新派生表,我会改写为:
update voyage_port
set port_seq = t.new_seq
from
voyage_port p
inner join
(select voyage_port_id, voyage_id, arrival_date, port_seq,
row_number() over (partition by voyage_id order by arrival_date) as new_seq
from voyage_port) t
on p.voyage_port_id = t.voyage_port_id
答案 3 :(得分:-2)
UPDATE之后的第一个标记应该是要更新的表的名称,然后是要更新的列。我不确定你想用select语句实现什么,但你可以'从合法选择中更新结果集。
一个版本的sql,猜测你的想法,可能看起来像......
update voyage_port t
set t.port_seq = (<select statement that generates new value of port_seq>)
注意:要使用select语句来设置这样的值,您必须确保从select中只返回1行!
编辑:上面的修改声明反映了我试图解释的内容。 Andomar上面已经很好地回答了这个问题