0

この表を検討してください。

テーブル:ORDER列:id、order_num、order_date、order_status

このテーブルには100万件のレコードがあります。入力テキストファイルから読み取るorder_numの束(約10,000)に対して、order_statusを値「5」に更新したいと思います。

My SQL could be:
(A) update ORDER set order_status=5 where order_num in ('34343', '34454', '454545',...)
OR
(B) update ORDER set order_status=5 where order_num='34343' 

10,000件の注文の更新をカバーするまで、この更新を数回ループできます。(また、ORDER_ITEMSのようなORDERの子テーブルがほとんどないことに注意してください。同様のステータスを更新して情報を監査する必要があります)

私の問題は次のとおりです
。別のORDER_AUDITテーブルでこの更新を監査するにはどうすればよいですか:
Order_Num:34343-正常に更新されました
Order_Num:34454-注文が見つかりません
Order_Num:454545-正常に更新されました
Order_Num:45457-注文が見つかりません

(A)のようにバッチ更新を行うと、注文レベルで監査できません。
(B)のように、更新時にシングルオーダーを選択した場合、10,000回ループする必要がありますが、これは非常に遅い場合がありますが、この場合はオーダーレベルで監査できます。

他に方法はありますか?

4

3 に答える 3

1

まず、「入力テキストファイル」の上に外部テーブルを作成します。このようにして、単純な単一のUPDATEステートメントを実行できます。

update ORDER 
set order_status=5 
where order_num in ( select col1 from ext_table order by col1)

きちんと効率的。(サブクエリの並べ替えはオプションです。更新のパフォーマンスが向上する可能性がありますが、重要な点は、外部テーブルを通常のテーブルのように扱い、SELECT構文の全容を使用できることです。) 詳細をご覧ください

次に、RETURNING句を使用して、ヒットをキャプチャします。

update ORDER 
set order_status=5 
where order_num in ( select col1 from ext_table order by col1)
returning order_num bulk collect into l_nums;

l_numsこのコンテキストでは、タイプ番号のPL/SQLコレクションです。RETURNING句は、更新された行のすべてのORDER_NUM値のみを提供します。 詳細をご覧ください

の型をSQLネストテーブルオブジェクトl_numsとして宣言すると、監査用の以降のSQLステートメントで使用できます。

 insert into order_audit 
 select 'Order_Num: '||to_char(t.column_value)||' - Updated Succesfully'    
 from table ( l_nums ) t
 /

 insert into order_audit 
 select 'Order_Num: '||to_char(col1)||' - Order Not Found'    
 from ext_table 
 minus 
 select * from table ( l_nums ) 
 /

パフォーマンスに関する注意:

入力テキストファイルにある行の数が一致するかどうかはわかりません。おそらくあなたは知らないでしょう(実際に読み直すと、10,000がファイル内の行数なのか一致する行数なのかは明確ではありません)。Pl / SQLコレクションはプライベートセッションメモリを使用するため、非常に大きなコレクションはPGAを破壊する可能性があります。ただし、1万個のNUMBERインスタンスに問題なく対処できるはずです。

私の解決策では、外部テーブルを2回読み取る必要があります。これは問題にはならないはずです。そして、それは確かに、1000個の数の100個のIN句を動的に組み立ててそれぞれをループするよりもはるかに高速です。

更新は、多くの場合、人に知られている最も遅い一括操作であることに注意してください。それらを高速化する方法はいくつかありますが、それらの方法はかなり複雑になる可能性があります。ただし、これが頻繁に実行したいことであり、パフォーマンスが問題になる場合は、このOraFAQの記事を読む必要があります。

于 2013-02-17T04:56:19.623 に答える
0

MERGEを使用します。まず、列IDが1つだけのORDER_UPD_TMPという一時テーブルにデータをロードします。SQLDeveloperのインポート機能を使用してこれを行うことができます。次に、ベーステーブルを更新するためにMERGEを使用します。

MERGE INTO ORDER b
USING (
  SELECT order_id
  FROM ORDER_UPD_TMP 
) e
ON (b.id = e.id)
WHEN MATCHED THEN
  UPDATE SET b.status = 5

レコードが一致しない場合は、別のステータスで更新することもできます。詳細については、ドキュメントを確認してください。

http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm

于 2013-02-16T19:21:02.570 に答える
-1

最善の方法は次のとおりだと思います。

  • 最初にファイルをデータベースにインポートします
  • 次に、1つのトランザクションでいくつかのSQL UPDATE / INSERTクエリを実行してstatus、すべての注文を更新し、監査レコードを作成します。
于 2013-02-16T21:08:11.503 に答える