2011-02-01 7 views
2

DB 테이블의 일부 행을 업데이트해야합니다. 업데이트 할 행을 식별하는 방법은 일련의 복잡한 명령문과 관련되어 있으며 일련의 WITH 문을 사용하여이를 해결할 수있었습니다. 이제 올바른 데이터 값을 가지고 테이블을 업데이트해야합니다.DB2 WITH 문을 UPDATE 또는 MERGE의 일부로 사용할 수 있습니까?

WITH 문을 사용하여이 값을 얻을 수 있었기 때문에 UPDATE/MERGE에서이 값을 사용하고 싶습니다. 다음은 간단한 예제입니다.

with data1 
(
    ID_1 
) 
as 
(
    Select ID 
    from ID_TABLE 
    where ID > 10 
) 
, 
cmedb.data2 
(
    MIN_ORIGINAL_ID 
    ,OTHER_ID 
) 
as 
(
    Select min(ORIGINAL_ID) 
      ,OTHER_ID 
    from OTHER_ID_TABLE 
    where OTHER_ID in 
    (
     Select distinct ID_1 
     From data1 
    ) 
    group by OTHER_ID 

) 
select MIN_ORIGINAL_ID 
     ,OTHER_ID 
from cmedb.data2 

이제 두 개의 데이터 열이 있으므로 테이블을 업데이트하는 데 사용하고 싶습니다. 따라서 선택 항목이 맨 아래에있는 대신 UPDATE/MERGE 위의 WITH 문이나 UPDATE/MERGE 문의 일부로 병합과 업데이트의 모든 조합을 시도했습니다. 다음은 내 마음에서 내가하고 싶은 것에 가장 가까운 것입니다 :

merge into ID_TABLE as it 
using 
(
    select MIN_ORIGINAL_ID 
      ,OTHER_ID 
    from cmedb.data2 

) AS SEL 
ON 
(
    it.ID = sel.OTHER_ID 
) 
when matched then 
update 
set it.ORIGINAL_ID = sel.MIN_ORIGINAL_ID 

그래서 작동하지 않습니다. 나는 UPEATE 또는 MERGE와 함께 WITH 문을 사용하여 인터넷에서 예제를 찾지 못했기 때문에 이것이 가능한지 확신 할 수 없습니다. INSERT와 함께 사용되는 WITH 문에 대한 예가 있으므로 가능할 수도 있습니다.

도움이 될만한 사람이 있으면 도움이 될 것입니다. 문제를 해결하는 데 유용한 정보를 빠뜨린 경우 알려 주시기 바랍니다.

면책 조항 : 내가 제공 한 예는 제가하려고하는 것에 대한 차가운 버전이며 실제 의미가 없습니다.

답변

4

@Andrew White에 따르면 MERGE 문에서 공통 테이블 식을 사용할 수 없습니다.

그러나 중첩 된 subselect를 사용하여 공통 테이블 식을 제거 할 수 있습니다. 여기에 중첩 된 부속 선택을 사용하여 다시 작성하여 예를 select 문입니다 :

select min_original_id, other_id 
from (
    select min(original_id), other_id 
    from other_id_table 
    where other_id in (
     select distinct id_1 from (select id from id_table where id > 10) AS DATA1 (ID_1) 
    ) 
    group by other_id 
) AS T (MIN_ORIGINAL_ID, OTHER_ID); 

이 다소 복잡하다이 (정확한 문이 더 잘 쓸 수있다),하지만 난 당신이 그냥 간단한 예를주고 있다고 알고 있습니다.

일반 테이블 식 대신 중첩 된 subselects를 사용하여 MERGE 문을 다시 작성할 수 있습니다. 확실히 구문 적으로 가능합니다. 예를 들어

:

merge into other_id_table x 
using (
    select min_original_id, other_id 
    from (
     select min(original_id), other_id 
     from other_id_table 
     where other_id in (
     select distinct id_1 from (select id from id_table where id > 10) AS DATA1 (ID_1) 
    ) 
     group by other_id 
    ) AS T (MIN_ORIGINAL_ID, OTHER_ID) 
) as y 
on y.other_id = x.other_id 
when matched 
    then update set other_id = y.min_original_id; 

는 다시,이 뒤얽힌하지만, 그것은 적어도 수 있음을 보여줍니다.

+0

우수. 이것이 제가 끝내 준 것입니다. 동료가 실제로 이렇게하는 것이 좋습니다. 나는 그를 무시했습니다 ... – Clarkey

1

나는 지금 문법을 찾고 있는데 대답은 '아니오'라고 확신한다. 적어도 DB2 버전에서 마지막으로 사용하지 않았습니다. 구문에 대해서는 updatemerge doc 페이지를 살펴보십시오. 구문에서 fullselect이 표시 되더라도 withselect doc 페이지에 따라 명시 적으로 분리되어 있으므로 사용할 수 없습니다.

+0

확인, 감사합니다 . – Clarkey

1

DB2 V8 이상을 실행중인 경우 WITH 문을 사용하여 쿼리를 UPDATE/INSERT 할 수있는 흥미로운 SQL 해킹 here이 있습니다. 예비 데이터 준비가 많이 필요한 삽입 인 & 업데이트의 경우이 방법은 많은 명확성을 제공합니다.

여기에서 하나의 수정 - UPDATE 문에서 선택하는 것이 V9에서 처음 소개되었으므로 V8 이상의 삽입 및 V9 이상의 업데이트에 위의 내용이 적용됩니다.

0

또 다른 방법은 단순히 WITH 쿼리를 대체하고 subselects 만 사용하는 것입니다. 예를 들어

, 당신은했다 (내가 논리, 집계 함수 (MAX)과 GROUP BY, 그냥 더 현실 세계를 보여 일부와 다소 복잡한 예를 포함하려고)하는 경우 :

WITH 
    Q1 AS (
    SELECT 
     A.X, 
     A.Y, 
     A.Z, 
     MAX(A.W) AS W 
    FROM 
     TABLEB B 
     INNER JOIN TABLEA A ON B.X = A.X AND B.Y = A.Y AND B.Z = A.Z 
    WHERE A.W <= DATE('2013-01-01') 
    GROUP BY 
     A.X, 
     A.Y, 
     A.Z 
), 

    Q2 AS (
    SELECT 
     A.X, 
     A.Y, 
     A.Z, 
     A.W, 
     MAX(A.V) AS V 
    FROM 
     Q1 
     INNER JOIN TABLEA A ON Q1.X = A.X AND Q1.Y = A.Y AND Q1.Z = A.Z AND Q1.W = A.W 
    GROUP BY 
     A.X, 
     A.Y, 
     A.Z, 
     A.W 
) 

SELECT 
    B.U, 
    A.T 
FROM 
    Q2 
    INNER JOIN TABLEA A ON Q2.X = A.X AND Q2.Y = A.Y AND Q2.Z = A.Z AND Q2.W = A.W AND Q2.V = A.V) 
    RIGHT OUTER JOIN TABLEB B ON Q2.X = B.X AND Q2.Y = B.Y AND Q2.Z = B.Z 

... 당신은 수행하여 병합 INTO에 적합한 무언가로이를 돌 수 있었다 다음

  1. 상단
  2. 에서 WITH를 제거 폐쇄 후합니다 (Q1 블록의 끝에서 쉼표를 제거 괄호)
  3. 여는 괄호 앞에서 Q1 AS를 취하고 괄호를 끝내고 (쉼표를 제거한 후) AS를 Q1 앞에 놓습니다.
  4. 이 새로운 Q1 블록을 가져 와서 FROM Q1 다음에 Q2 블록에 붙여 넣습니다 (Q1을 클립 보드에서 쿼리로 바꾸십시오). 참고 : Q1에 대한 다른 참조는 홀로 남겨두고, 당연하지.
  5. 이제 더 큰 Q2 쿼리가 생성되었습니다. 3 단계와 4 단계를 다시 수행하십시오. 이번에는 메인 선택의 Q2 (FROM 뒤)를 클립 보드의 더 큰 Q2 쿼리로 바꾸십시오. 실제로 지금 (내 자신의 개인적인 경험에서이 작업을 수행 한

    SELECT 
        B.U, 
        A.T 
    FROM 
        (SELECT 
        A.X, 
        A.Y, 
        A.Z, 
        A.W, 
        MAX(A.V) AS V 
        FROM 
        (SELECT 
         A.X, 
         A.Y, 
         A.Z, 
         MAX(A.W) AS W 
         FROM 
         TABLEB B 
         INNER JOIN TABLEA A ON B.X = A.X AND B.Y = A.Y AND B.Z = A.Z 
         WHERE A.W <= DATE('2013-01-01') 
         GROUP BY 
         A.X, 
         A.Y, 
         A.Z) AS Q1 
        INNER JOIN TABLEA A ON Q1.X = A.X AND Q1.Y = A.Y AND Q1.Z = A.Z AND Q1.W = A.W 
        GROUP BY 
         A.X, 
         A.Y, 
         A.Z, 
         A.W) AS Q2 
    INNER JOIN TABLEA A ON Q2.X = A.X AND Q2.Y = A.Y AND Q2.Z = A.Z AND Q2.W = A.W AND Q2.V = A.V 
    RIGHT OUTER JOIN TABLEB B ON Q2.X = B.X AND Q2.Y = B.Y AND Q2.Z = B.Z 
    

    : 결국

, 당신은 (적절한 들여 쓰기를 보여 포맷)이 보이는 직선 SELECT 질의를해야합니다) 완벽하게 작동합니다.

행운을 비네.

0

CTE를보기에 놓고 병합의보기에서 선택하십시오. 그렇게하면 깨끗하고 읽기 쉬운보기를 얻을 수 있으며 깨끗하고 읽기 쉬운 병합이 가능합니다.

0

UPDATE (및 너무 INSERT) UPDATE 문 FROM SELECT를 사용 (here)와 문 를 사용하는 방법 : 기준 및 빠른 응답

WITH TEMP_TABLE AS (
    SELECT [...] 
) 
SELECT * FROM FINAL TABLE (
    UPDATE TABLE_A SET (COL1, COL2) = (SELECT [...] TEMP_TABLE) 
    WHERE [...] 
); 
관련 문제