2017-02-02 2 views
0

複雑なソースデータセットのテーブルを更新しようとしています。製品の在庫情報を含む表区画があります。フィールド製品の説明も含まれています。このフィールドにはいくつかの古い説明があり、基本データテーブルによって更新する必要があることがあります。複雑な結合による更新

しかし、結合された表は、別の副選択または結合によって行われる言語によってもフィルタリングされる必要があります。

SELECT products.DESCSH as old_desc 
     ,parcel.DESCSH as new_desc 
    FROM parcel 
     ,products 
    WHERE parcel.PRODU_INTERNUM = products.INTERNUM 
    AND parcel.NUM LIKE '2%REGEN' 
    and (SELECT COMPA.LANG FROM COMPA WHERE COMPA.NUM = parcel.COMPA_NUM) = products.LANG 
    and trim(upper(products.DESCSH)) <> trim(upper(parcel.DESCSH)) 

これはベースセレクトです。 (タスクは基本的にnew_descをold_descで更新することです)

私はこれを行う方法がわからなかったので、私はここで3つの方法を見ました。それだけで400件のレコードを更新する必要があり、それが無限ループ(さらに多くの無知)で立ち往生なぜか私は無知だときMERGEアプローチ

merge into gc_prcel target 
    using (
     Select p.descsh 
       ,p.internum 
      from p 
       ,par 
      where sysdate between p.vldty_beg and p.vldty_end 
      and p.internum = par.produ_internum 
      and p.lang = (SELECT COMPA.LANG FROM COMPA WHERE COMPA.NUM = par.COMPA_NUM) 
     ) source 
    on (target.produ_internum = source.internum) 
    when matched then update 
    set target.descsh = source.descsh 
    where target.num like '2%REGENSDO' 
    and trim(upper(target.descsh)) <> trim(upper(target.descsh)); 

この1どちらかはほぼ全テーブルを更新します。私はそれが奇妙に見えることを知っています。

EXIST句(私はこの1つを使用することができますが、私は他のアプローチは、よりエレガント見つける。)そしてあなたが直接そのような副選択からフィールドを更新1と方法:この1つはスロー

update 
    (SELECT products.DESCSH as old_desc 
      ,parcel.DESCSH as new_desc 
     FROM parcel 
      ,products 
     WHERE parcel.PRODU_INTERNUM = products.INTERNUM 
     AND parcel.NUM LIKE '2%REGENSDO' 
     and (SELECT COMPA.LANG FROM COMPA WHERE COMPA.NUM = parcel.COMPA_NUM) = products.LANG 
     and trim(upper(products.DESCSH)) <> trim(upper(parcel.DESCSH))) descriptions 
    set descriptions.new_desc = descriptions.old_desc; 

(ORA-01779:キー保存されていない表にマップする列は変更できません)

マージ・ステートメントでも実行しようとしているタスクですか、または存在とその理由を使用して更新を使用する必要がありますか私の最初のアプローチはORA-01779で失敗します)

答えて

0

MERGEとUPDATEの両方でスマートなことをしています。これは、値が変更されたときだけ行を更新することです。しかし、あなたはMERGEでこれを書きました - 間違いを見つけられますか? (おそらく、理由の1つ、または長い実行時間の理由の1つです)。

これは推測ゲームではありません。引数の1つがsource.deschsである必要があります。両側にtargetがあります。

編集:実際には、この条件がTRUEになることはないため、ステートメントは何も更新されません。それはあなたが使った言葉ですか? 終了編集

UPDATEとエラーについては、この短い記事をStack Overflowの「Documentation」ドメインに書きました。それはあなたが得たエラーを説明し、それを修正する方法:Update with joins

+0

こんにちは:しかし、それはあなたが更新しようとしている土地区画テーブルですが、場合

merge into gc_prcel target using ( Select p.descsh ,p.internum from p inner join par on p.internum = par.produ_internum and trim(upper(p.descsh)) <> trim(upper(par.descsh) where sysdate between p.vldty_beg and p.vldty_end and p.lang = (SELECT COMPA.LANG FROM COMPA WHERE COMPA.NUM = par.COMPA_NUM) and par.num like '2%REGENSDO'); ) source on (target.produ_internum = source.internum) when matched then update set target.descsh = source.descsh; 

は、私のようなものでいいと思います。あなたの素早い答えに感謝しています...実際には、これは私が最後に使ったステートメントでした。実行を中止しないのでキャンセルする必要がありました –

+0

@JanZimmermann - それは本当に奇妙です。あなたは、いくつかの実行では、ステートメントが多くの行を更新したと言っていましたが、 'where'節は決してTRUEではありません(何かがそれ自体と異なることは決して真実ではありません)。では、それはどのように可能ですか? – mathguy

+0

はい私はあなたが何を意味しているか知っています:)しかし、私はこのステートメントのさまざまなバリエーションをたくさん試してみました。もしそれがエラーを投げたり無限に実行しなかったならば、400の代わりに80kのレコードを更新します。もう私には利用できません。 Btw私はすでにタスクを実行する必要があったので、私は存在するメソッドを使用しました。しかし、私はまだマージステートメントでそのタスクを達成することができたのは不思議です –

0

gc_prcelとパーは(私はこれが本当にあなたの更新文で言及小包テーブルであると仮定?)別のテーブルである場合、私は思いますマージ、のようなもの:

merge into parcel tgt 
    using (select p.internum, 
       p.descsh, 
       compa.num 
     from products p 
       inner join compa on p.lang = compa.lang 
     where sysdate between p.vldty_beg and p.vldty_end) src 
    on (tgt.produ_internum = src.internum 
     and tgt.num like '2%REGENSDO' 
     and tgt.compa_num = src.compa_num) 
when matched then 
    update set tgt.descsh = src.descsh 
    where  trim(upper(tgt.descsh)) != trim(upper(src.descsh)); 
+0

素早く答えてくれてありがとう(私はあなたたちが:)私は今すぐテストする時間がありませんが、明日の朝にそれを最初に行います。そしてyes gc_prcelとparcelは同じです(私は実際のオブジェクト名を投稿しないように注意しています)// –

+0

sub-subselectでは、par.compa_numを参照していますが、どこにも設定されているparエイリアスはありません。私はcompa_numだけがそこに利用可能で、私は言語(LANG)を決定するためにそのフィールドが必要なので、私は副選択でパーセルテーブルに参加する必要があると思う。 –

+0

良い点。それについて考える必要があります、ありがとう! – Boneist

関連する問題