web-dev-qa-db-ja.com

DB2のUPDATE SQLの内部結合

DB2の更新ステートメントで結合を使用する方法はありますか?

グーグルは本当にこれに私を失望させました

これは私が達成しようとしているおおよそのものです(...明らかに明らかに働いていることを除いて...)

update file1 inner join file2                                 
       on substr(file1.firstfield,10,20) = substr(file2.anotherfield,1,10)                                                                    
set file1.firstfield = ( 'BIT OF TEXT' concat file2.something )                                                                             
where file1.firstfield like 'BLAH%'                             

乾杯

13
Hamish

どのプラットフォームをターゲットにしているのか言わないでください。ただし、テーブルをファイルとして参照すると、Linux、UNIX、またはWindows(LUW)でDB2を実行しているのではないと考えることになります。

ただし、DB2 LUWでareである場合は、 [〜#〜] merge [〜#〜] ステートメントを参照してください。

例のステートメントでは、これは次のように記述されます。

merge into file1 a
   using (select anotherfield, something from file2) b
   on substr(a.firstfield,10,20) = substr(b.anotherfield,1,10)
when matched and a.firstfield like 'BLAH%'
   then update set a.firstfield = 'BIT OF TEXT' || b.something;

注:DB2の場合、SUBSTR関数の3番目の引数は、終了位置ではなく、返すバイト数です。したがって、SUBSTR(a.firstfield、10,20)はCHAR(20)を返します。ただし、SUBSTR(b.anotherfield、1,10)はCHAR(10)を返します。これが意図的に行われたかどうかはわかりませんが、比較に影響する可能性があります。

8
Ian Bjorhovde

updateステートメントの結合は非標準であり、すべてのベンダーでサポートされているわけではありません。あなたがしようとしていることは、サブセレクトで達成できます:

update
  file1
set
  firstfield = (select 'stuff' concat something from file2 where substr(file1.field1, 10, 20) = substr(file2.xxx,1,10) )
where
  file1.foo like 'BLAH%'
7
Donnie

これを試して、結果を教えてください:

UPDATE File1 AS B                          
SET    b.campo1 = (SELECT DISTINCT A.campo1
                   FROM  File2 A           
                   INNER JOIN File1      
                   ON A.campo2 = File1.campo2 
                   AND A.campo2 = B.campo2) 
6
eduardo

回答の更新 https://stackoverflow.com/a/4184237/565525

複数の列が必要な場合は、次のように達成できます:

update file1
set
  (firstfield, secondfield) = (
        select 'stuff' concat 'something from file2', 
               'some secondfield value' 
        from file2
        where substr(file1.field1, 10, 20) = substr(file2.xxx,1,10) )
where
  file1.foo like 'BLAH%'

ソース: http://www.dbforums.com/db2/1615011-sql-update-using-join-subquery.html#post6257307

4
Robert Lujo

ここに私が仕事をしたばかりの良い例があります:

update cac c
set ga_meth_id = (
    select cim.ga_meth_id 
    from cci ci, ccim cim 
    where ci.cus_id_key_n = cim.cus_id_key_n
    and ci.cus_set_c = cim.cus_set_c
    and ci.cus_set_c = c.cus_set_c
    and ci.cps_key_n = c.cps_key_n
)
where exists (
    select 1  
    from cci ci2, ccim cim2 
    where ci2.cus_id_key_n = cim2.cus_id_key_n
    and ci2.cus_set_c = cim2.cus_set_c
    and ci2.cus_set_c = c.cus_set_c
    and ci2.cps_key_n = c.cps_key_n
)
3
Justin

条件に一致する行のみを更新し、他の行のNULLを更新しないようにするだけです。

update table_one set field_1 = 'ACTIVE' where exists 
(select 1 from table_two where table_one.customer = table_two.customer);

DB2/AIX64 9.7.8で動作します

1
Antonio

DB2 LUW 9.7の PDATEステートメント のリファレンスドキュメントには、次の例があります。

   UPDATE (SELECT EMPNO, SALARY, COMM,
     AVG(SALARY) OVER (PARTITION BY WORKDEPT),
     AVG(COMM) OVER (PARTITION BY WORKDEPT)
     FROM EMPLOYEE E) AS E(EMPNO, SALARY, COMM, AVGSAL, AVGCOMM)
   SET (SALARY, COMM) = (AVGSAL, AVGCOMM)
   WHERE EMPNO = '000120'

UPDATEの後の括弧には全選択を含めることができます。つまり、任意の有効なSELECTステートメントをそこに置くことができます。

それに基づいて、私は以下を提案します:

UPDATE (
  SELECT
    f1.firstfield,
    f2.anotherfield,
    f2.something
  FROM file1 f1
  WHERE f1.firstfield like 'BLAH%' 
  INNER JOIN file2 f2
  ON substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10)
)
AS my_files(firstfield, anotherfield, something)
SET
  firstfield = ( 'BIT OF TEXT' || something )

編集:イアンは正しい。私の最初の本能は、代わりにサブセレクトを試すことでした:

UPDATE file1 f1
SET f1.firstfield = ( 'BIT OF TEXT' || (
  SELECT f2.something
  FROM file2 f2
  WHERE substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10)
))
WHERE f1.firstfield LIKE 'BLAH%' 
AND substr(f1.firstfield,10,20) IN (
  SELECT substr(f2.anotherfield,1,10)
  FROM file2 f2
)

しかし、連結が機能するかどうかはわかりません。また、部分文字列間に1:1のマッピングがあると想定しています。一致する行が複数ある場合、機能しません。

0
Leons

あなたが尋ねるから

update file1 f1
set file1.firstfield=
(
select 'BIT OF TEXT' || f2.something
from file2 f2
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10)
)
where exists
(
select * from file2 f2
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10)
)
and f1.firstfield like 'BLAH%'

結合により複数の結果が得られる場合は、このような更新を強制できます

update file1 f1
set file1.firstfield=
(
select 'BIT OF TEXT' || f2.something
from file2 f2
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10)
fetch first rows only
)
where exists
(
select * from file2 f2
where substr(f1.firstfield,10,20) = substr(f2.anotherfield,1,10)
)
and f1.firstfield like 'BLAH%' 

テンプレートメソッド

update table1 f1
set (f1.field1, f1.field2, f1.field3, f1.field4)=
(
select f2.field1, f2.field2, f2.field3, 'CONSTVALUE'
from table2 f2
where (f1.key1, f1.key2)=(f2.key1, f2.key2) 
)
where exists 
(
select * from table2 f2
where (f1.key1, f1.key2)=(f2.key1, f2.key2)
) 
0
Esperento57