基于子查询的更新失败
我正在尝试在 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:数据操作操作在此视图上不合法
有什么问题以及如何避免它?
I am trying to do the following update in 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 is the primary key, voyage_id is a foreign key. I'm trying to assign a sequence number based on the dates within each voyage.
However, the above fails with ORA-01732: data manipulation operation not legal on this view
What is the problem and how can I avoid it ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
由于您无法使用
row_number
更新子查询,因此您必须在更新的set
部分计算行号。起初我尝试了这个:但这不起作用,因为子查询只选择一行,然后
row_number()
始终为 1。使用另一个子查询可以得到有意义的结果:它可以工作,但是比我对这项任务的预期更复杂。
Since you can't update subqueries with
row_number
, you'll have to calculate the row number in theset
part of the update. At first I tried this:But that doesn't work, because the subquery only selects one row, and then the
row_number()
is always 1. Using another subquery allows a meaningful result:It works, but more complex than I'd expect for this task.
您可以更新某些视图,但有一些限制,其中之一是视图不得包含分析函数。请参阅有关 UPDATE 的 SQL 语言参考并搜索第一次出现的“analytic”。
如果航程在同一天访问多个港口(或者日期包含使它们独一无二的时间部分),则这将起作用:
我认为这可以处理航程每天访问超过 1 个港口且没有时间部分(尽管同一天访问的端口顺序是任意的):
You can update some views, but there are restrictions and one is that the view must not contain analytic functions. See SQL Language Reference on UPDATE and search for first occurence of "analytic".
This will work, provided no voyage visits more than one port on the same day (or the dates include a time component that makes them unique):
I think this handles the case where a voyage visits more than 1 port per day and there is no time component (though the sequence of ports visited on the same day is then arbitrary):
不要认为您可以更新派生表,我将重写为:
Don't think you can update a derived table, I'd rewrite as:
UPDATE 之后的第一个标记应该是要更新的表的名称,然后是要更新的列。我不确定您想通过 select 语句实现什么目的,但您可以合法地更新 select 的结果集。
猜测您的想法,sql 的一个版本可能看起来像...
注意: 要使用 select 语句来设置这样的值,您必须确保仅返回 1 行选择!
编辑:修改上面的语句以反映我试图解释的内容。上面的安多马尔已经很好地回答了这个问题
The first token after the UPDATE should be the name of the table to update, then your columns-to-update. I'm not sure what you are trying to achieve with the select statement where it is, but you can' update the result set from the select legally.
A version of the sql, guessing what you have in mind, might look like...
NOTE: to use a select statement to set a value like this you must make sure only 1 row will be returned from the select !
EDIT : modified statement above to reflect what I was trying to explain. The question has been answered very nicely by Andomar above