题
我试图做的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:数据操纵操作在此视图中强>
不合法这是什么问题,我怎么能避免呢?
解决方案
既然你不能更新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
)
它的工作原理,但更复杂的比我预期这个任务。
其他提示
可以更新一些视图,但有限制,一个是该视图中不能包含解析函数。请参见 SQL语言参考上更新和搜索的第一次出现的“分析”。
这将工作,没有提供航程访问多于一个的端口在同一天(或日期包括时间分量,这使得它们是唯一的):
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
)
)
不要以为你可以更新派生表,我会为改写:
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
更新后的第一个记号应该是表的名称进行更新,那么你列到更新。我不知道你正在努力实现与SELECT语句的地方是什么,但你可以”的更新的结果从选择设置459。结果 在SQL的一个版本,猜测你有什么想法,可能看起来像......
update voyage_port t
set t.port_seq = (<select statement that generates new value of port_seq>)
注意:,以使用select语句来设置这样的价值,你必须确保只有1行将从选择返回
编辑:上述修改声明以反映什么,我试图解释。该问题已回答非常漂亮通过Andomar上述
不隶属于 StackOverflow