サブクエリに基づいてアップデートが失敗しました
質問
私は、Oracle 10gリリース2で、次の更新を実行しようとしています:
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
)
しかし、サブクエリが1行のみ選択し、次いで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
)
これは動作しますが、私はこの作業のために期待するよりも、より複雑ます。
他のヒント
あなたは、いくつかのビューを更新することができますが、制限があり、もう一方はビューが分析関数を含んではならないということです。 UPDATE の上 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日以上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
UPDATE後の最初のトークンは、あなたの列-に更新、更新するテーブルの名前でなければなりません。私はあなたはそれがあるselect文で達成しようとしているかわからないんだけど、あなたのことができ」の更新の法的選択の結果セット。
SQLのバージョンは、あなたが心の中に持っているものを推測し、
update voyage_port t
set t.port_seq = (<select statement that generates new value of port_seq>)
注:!のあなただけの1行が選択から返されることを確認する必要があり、このように値を設定するために、SELECT文を使用する
編集:私は説明しようとしていたものを反映するために、上記の変更のステートメント。質問は、
上Andomarすることにより、非常にきれいに回答されています