2016-11-10 1 views
10

の状態は、mytableは、以下の行を想定し、「前」を返すことができます。OracleではのOracle SQLは、私は列の値

id  = 1 
letter = 'a' 

を、人は簡単に以下のことが可能です。

update myTable set 
    letter = 'b' 
where id = 1 
returning letter 
into myVariable; 

とmyVariableは値 'b'を保持します。私が探しています何

は手紙

すなわちの値「の前に」を返すいくつかの方法です。前回の更新置き換える:

update myTable set 
    letter = 'b' 
where id = 1 
returning letter "before the update" 
into myVariable; 

とmyVariable変数はその後、「」値を保持する必要がありますが、

私はT-SQLは、OUTPUT句を経てこれを達成できることを理解しています。

は、これを実現するOracleの同等の方法は、私が最初にちょうど前の値を取得するには、「選択」を行う必要はありませんありますか?

答えて

8
update 
    (
    select T.*, (select letter from DUAL) old_letter 
    from myTable T 
    where id=1 
) 
    set letter = 'b' 
returning old_letter into myVariable; 

11.2

+3

これは興味深いです。 –

+0

ブリリアント溶液!これはちょっと単純化することができます。ちょうど 'select T. *、T.letter AS old_letter .....' – krokodilko

+2

@krokodilko私は "簡略化された"文字をold_letterとしてテストしました。この場合、Oracleは新しい値を返します。 subselectのみがオラクルを騙す – Mike

1

一つの方法は、別の列とトリガを使用することができた(マイクス回答:-)を見て、私は間違っている)私はあなたが単純なSQL文でそれを行うことはできませんと信じて。アップデートを実行すると

create table testUpdate(a number, old_a number); 
create or replace trigger trgUpdate 
before update on testUpdate 
for each row 
begin 
    if :new.a != :old.a then /* assuming not null values for simplicity */ 
     :new.old_a := :old.a; 
    end if; 
end; 
insert into testUpdate values (1, null); 

は、古い値は次のとおりです。たとえば、あなたがaの古い値を保存し、トリガとそれを埋めるために別の列old_aを追加することができ、あなたが列aを持つテーブルを持っていると言いますreturning句で目old_a列に格納されていると返さ

SQL> declare 
    2  vA number; 
    3 begin 
    4  update testUpdate 
    5  set a = 9 
    6  returning old_a 
    7  into vA; 
    8  -- 
    9  dbms_output.put_line(vA); 
10 end; 
11/
1 

しかし、これは、私は私が持っていると思います。このソリューション何かよりももっと運動を考えるあなたのテーブルに列とトリガーを追加する必要があることを与えられましたプロダクションDB

+0

おかげで非常に多くの@Aleksej - マイクに私のコメントあたりとしては、私はselectを選択し、この方法で更新します。しかし、あなたの答えは、私が奇妙なことを強調していると思います。つまり、Oracleトリガーは古い値と新しい値にアクセスできますが、私がここで見ている回答から、SQLを介して同じ機能を公開するわけではありません。そのためのユースケースは非常に多く、私はそれらをすべてリストすることさえできませんでした。 – Pancho

1

あなたがループでアップデートを行うと、古い値を取得することができます多くのアップデートがない場合は、次のOracleでテスト

declare 
CURSOR c IS SELECT letter, id FROM myTable 
    FOR UPDATE OF letter; 
begin 
    open c; 
    for x in c loop 
    -- old value is in x.letter. You can assign it here 
    update myTable set letter = 'b' where id = x.id;  
    end loop; 
    commit; 
    close c; 
end; 
/
+0

ありがとう@Kacper - 私はこのアプローチよりもselectを使って更新することを好むだろうと思う。 – Pancho

+0

@Panchoはい私はまた、選択がより良いと思う。 – Kacper

関連する問題