0

Oracleで複数の列を更新しようとしていますが、いくつかのシナリオを経た後、以下のコードに落ち着きました。

私の問題は、より合理化されたコードが必要なものを更新していないのに対し、より複雑なものが更新されていないことです.数十万またはそれ以上の更新を見ているので、最小限の処理能力でこれを達成しようとしています.

したがって、最初のコードは次のとおりです。

UPDATE table@database1 i2 
SET    (i2.access, i2.permission) = 
(select 
i2m.access, i2m.permission 
from temporarytable ss
    JOIN table2 pgm 
     ON ss.secgroup = pgm.string 
   JOIN table i2m 
     ON pgm.hmy = i2m.hgroup 
        AND ss.pername = i2m.sobjname 
   JOIN table2@database1 pg 
     ON ss.secgroup = pg.string 

    WHERE 
    pg.string = 'string'  -- this limits the updates to a specific subset of data
    and i2m.hmy > 0 -- this for some freak records in both tables that are missing a primary key
    and pg.hmy = i2.hgroup -- this matches the key of the 'string' from above to the records i need to update
    and ss.pername = i2.sobjname -- further condition on which records to update. so only the ones that match from the temp table to the target table
    and ss.orig_hmy = i2.hmy) -- further condition to make sure i am updating only records matching between temp table and target table

さて、これを実行すると、上記のサブクエリに一致する約 700 レコードのみを更新する代わりに、テーブル 'table@database1' からすべてのレコードが更新され、その理由がわかりません (おそらく、私が理解していないことの 1 つです)。オラクル:))

しかし、以下を実行すると (唯一の違いは、サブクエリ全体を「存在する場所」に挿入することです)、これは必要なものだけを更新します。私の問題は、私が理解しているように、サブクエリが2回実行されることです.1回は更新で、もう1回はwhere句で実行されます.これは処理能力の無駄です.

UPDATE table@database1 i2 
SET    (i2.access, i2.permission) = 
(select 
i2m.access, i2m.permission 
from temporarytable ss
    JOIN table2 pgm 
     ON ss.secgroup = pgm.string 
   JOIN table i2m 
     ON pgm.hmy = i2m.hgroup 
        AND ss.pername = i2m.sobjname 
   JOIN table2@database1 pg 
     ON ss.secgroup = pg.string 

    WHERE 
    pg.string = 'string'
    and i2m.hmy > 0
    and pg.hmy = i2.hgroup
    and ss.pername = i2.sobjname
    and ss.orig_hmy = i2.hmy)

where exists (select 
i2m.access, i2m.permission 
from temporarytable ss
    JOIN table2 pgm 
     ON ss.secgroup = pgm.string 
   JOIN table i2m 
     ON pgm.hmy = i2m.hgroup 
        AND ss.pername = i2m.sobjname 
   JOIN table2@database1 pg 
     ON ss.secgroup = pg.string 

    WHERE 
    pg.string = 'string'
    and i2m.hmy > 0
    and pg.hmy = i2.hgroup
    and ss.pername = i2.sobjname
    and ss.orig_hmy = i2.hmy)

注: 表示されない場合、同じスキーマを持つ複数の DB があります。マスタースキーマからの情報を使用して、DB 間でテーブルを更新しようとしています。一時テーブルは、更新が必要な異なるレコードのリポジトリとして機能します。マスター スキーマとの違いが 15% しかない場合、何百万ものレコードを更新する必要はありません。

4

1 に答える 1

1

ここにいるすべての親切な人々から提案を受けた後、MERGEの使用を調べたところ、上記のクエリが以下に適応されました-成功したことが証明されました!

    MERGE INTO table@database1 i2 
    USING (
    select i2m.access, i2m.permission, ss.orig_hmy
    from table i2m
        JOIN table2 pgm 
         ON i2m.hgroup = pgm.hmy 
       JOIN temporarytable ss
         ON pgm.string = ss.string 
            AND ss.pername = i2m.sobjname 
       JOIN table2@database1 pg 
         ON ss.string = pg.string 
    WHERE 1 = 1
        and i2m.hmy > 0 
        and pg.string = 'string'
        and ss.database = 'database1' 
    ) u on (i2.hmy = u.orig_hmy)
    WHEN MATCHED THEN
        UPDATE SET i2.access = u.access, i2.permission = u.permission;

みんなに感謝します!

于 2016-07-29T01:04:14.510 に答える