2015-10-11 13 views
5

表では、A列とB列があります。Bの値を使用してAを更新し、Bを新しい値に更新したいとします。これは原子的に行わなければならない。oracleデータベースのupdate-set-clauseでの式の評価順序

これが働いているが、私はこの

-- Intially A = 1, B = 2 
UPDATE T SET A = B, B = 10 WHERE ID = 1; 
-- Now A = 2, B = 10 

ような何かをしようとしています、私はA = Bが最初に評価され、B = 10が後に評価されることを私が保証ドキュメントを見つけることができません。

私はあなたのテーブルから、キャッシュ内のデータは、そのキャッシュされた情報から読み込まれ、あなたは左のフィールド名を使用するとき、私は考えて最初のプールで、他のRDBMSと同様に、IMO oracle sql reference of the update statement

答えて

5

これは一般的なルールを定義するSQL標準で見つけることができます。
Oracleは、この規格に準拠していることを確認します。

こちらを参照してください - SQL 92: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

ページ393、章 "13.9 < UPDATE文:>を配置" ポイント6、)

6)>のが効果的です<値式は、オブジェクト行を更新する前に評価されます。 aにTの列への参照 が含まれている場合、オブジェクト行の値が に更新される前に、参照はオブジェクト行の列 の値になります。


は、一般的な更新の構文を考えてみましょう:<

UPDATE .... 
    SET <object column 1> = <value expression 1>, 
     <object column 2> = <value expression 2>, 
     ...... 
     <object column N> = <value expression N>; 


#6は、右側のすべての式は、行の任意の列を更新する前に、最初に評価されていることを述べているルール。
すべての式を評価する際に、古い行の値(更新前)のみが考慮されます。

+0

私はこの答えが正しいと確信していますが、これについてのOracleのドキュメント(「update」のANSIセマンティクスを実装していることさえある)でも参考にしたいと思います。 –

+1

この文書の内容:http://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_standard_sql003.htm#SQLRF55516オラクル社は、RDBMSが「E121-06、Positioned UPDATE文」に完全準拠していることを保証します。 SQL 2008標準です。 – krokodilko

1

を介してOracleに見えましたSETの側では、RDMBSは(変更前の)古いデータの値を読み込みます。

+2

Oracle(およびほとんどの他のDBMS)は、単一の行の更新で*表*をロックしません。 –

1

RDBMSでは(プログラミング言語とは異なり)評価の順序はありません。すべてが一度に完了します。あなたが最初の前の値に変数を設定し、それらの変数を使用するようなものだ:

SET a=b, b=a 

は単にabを切り替えます。

警告:SQL標準はアップデートで、任意の順序を保証するものではありません

SET temp=b, b=a, a = temp 
+1

「すぐに」完了していません。最初に右辺が評価され、その後実際の変更が行われます(実際には「一度に」とみなされます)。 –

0

:のようにのみMySQLは同じb値に両方のセットが得られ、それは完全に間違ってい、ここにあなたが一時変数が必要になりますステートメント。 2つの更新を希望の順序で実行して、正しい順序で更新されていることを確認することをお勧めします。

-- Intially A = 1, B = 2 
BEGIN TRANSACTION; 
UPDATE T SET A = B WHERE ID = 1; 
UPDATE T SET B = 10 WHERE ID = 1; 
COMMIT TRANSACTION; 
-- Now A = 2, B = 10 
+3

これは当てはまりません。 SQL標準は、左辺と右辺がどのように評価されるかについてかなり明確です –