문제

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 문으로 무엇을 달성하려고하는지 잘 모르겠지만, 당신은 할 수 있습니다. 업데이트 결과는 법적으로 선택한 것입니다.
SQL의 버전은 당신이 생각하는 것을 추측하는 것과 같은 모습을 보일 수 있습니다.

update voyage_port t
set t.port_seq = (<select statement that generates new value of port_seq>)

노트: Select 문을 사용하여 이와 같은 값을 설정하려면 Select에서 1 행만 반환해야합니다!

편집 : 내가 설명하려는 내용을 반영하기 위해 위의 수정 된 진술. 질문은 위의 Andomar에 의해 매우 멋지게 대답되었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top