2009-07-28 8 views
3

私は2列のテーブルを扱っています。単一の列のすべての行を更新する

表1:table_snapshot account_no | balance_due

表2:支払い済み account_no | post_balance | delta_balance

私は、次のコマンドを使用して、表2にする3番目の列を追加しました:

ALTER TABLE table_paid ADD delta_balance number(18); 

私は1間のバランスの違いで新しい列(delta_balance)を更新するために、次のクエリを使用しようとしていると2. FYI、table_paidはtable_snapshotのサブセットです。つまり、テーブル2にはテーブル1にいくつかのアカウントしかありません。SQLステートメントが正しく終了していないというエラーが表示されます。私が使用しているクエリは:

UPDATE table_paid 
SET table_paid.delta_balance = table_paid.post_balance - table_snapshot.balance_due 
from table_paid, table_snapshot 
WHERE table_paid.account_no = table_snapshot.account_no; 

誰かが私のクエリを訂正できるかどうかありがたいです。

多くのありがとうございます。

初心者。

答えて

4

Oracleは持っていません(table_paid.account_no = table_snapshot.account_no table_snapshot からbalance_dueを選択します)あなたがMS Sql Serverから使用しているUPDATE ... FROM構文(とにかく、ANSIではないと思います)。

UPDATE (SELECT tp.delta_balance 
       , tp.post_balance 
       , ts.balance_due 
      FROM table_paid tp 
        JOIN table_snapshot ts 
        ON tp.account_no = ts.account_no 
     ) 
    SET delta_balance = post_balance - balance_due; 

これは、より多くの「正しい」です:あなたは、結果セットの更新を行う必要があるときに、Oracleを使用すると、インライン・ビューの一種として結果セットを作成しているので、同様に代わり、、、あなたは、ビューを介して更新しますtable_snapshotに対応する行がない場合でも、クエリはtable_paidのすべての行を更新するため、Babarとpalindromによって提供される回答よりも優先されます。 1-1の対応がある場合は、心配する必要はありませんが、インライン表示で行う方が安全です。

あなたの例では、どのテーブルが親テーブルか(私が推測しているように)どちらも親テーブルではなく、account_noは別のテーブルの主キーを指しています(おそらくaccount、または "table_account"命名規則)。いずれにせよ、あなたのテーブルに1-1の対応がないことは明らかです.1つは15K、もう1つは数百万です。

これは、table_paidに対応する行がないか、table_paidの各行に対してtable_snapshotに多数の行があるtable_snapshotに多くの行があることを意味します。後者が本当の場合、あなたのクエリは不可能です - あなたはtable_paidの各行に対して複数の更新を行い、結果は予測できません。 "post_balance - balance_due"式のどれが特定のdelta_balanceの値を最終的に決定するかを、どのように知っていますか?

問合せを実行すると、すぐにこれを見つけることができます。「ORA-01779:非キー保存表にマップする列を変更できません」というエラー・メッセージが表示されます。このエラーは、テーブル内のデータに基づいて表示されません(大丈夫かもしれませんが、2つのテーブルに定義した主キーに基づいて表示されます)。指定した結合条件が、定義されたキーに基づいて、更新された表と結合の残りの部分との間に1-1の関係を明白にもたらさない場合は、このエラーが発生します。これはオラクルの「あなたのデータを台無しにしようとしている」ということです。

問題を引き起こす可能性のあるデータが実際にある場合は、他の回答ではエラー(この場合はORA-01427:複数行を戻す1行副問合せ)が返されます。私のバージョンはより厳格なので、他のバージョンを使う必要があるかもしれません。

他の人が言ったように、あなたは間違いなくtable_snapshotテーブルのaccount_noのインデックスが必要です。 table_paidで1つも怪我をしません。

+0

優秀な詳細情報をありがとう! – novice

4

この

UPDATE table_paid 
SET table_paid.delta_balance = table_paid.post_balance - 
(SELECT table_snapshot.balance_due from table_snapshot WHERE table_paid.account_no = 
table_snapshot.account_no); 
1

UPDATEが01​​SETのtable_paid.delta_balance = table_paid.post_balance table_paid試してみてください -

+0

こんにちはbabarとpalindrom クエリは完全なテーブルスキャンになり、実行中です。テーブル1には130万レコード、テーブル2には15キロレコードあります。 スキャンのスピードを上げる方法についてのご意見はありますか? – novice

+0

さらに読むために、Tom Kyteが多くの行の更新について何を言いたいのかを参照してください - http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:6407993912330 – jva

+1

createあなたが既に持っていない場合は、table1のインデックス(account_no)。 – palindrom

関連する問題