0

したがって、次のような従業員テーブルがあります。

empid | companyid | empnum | ...
  1   |     1     |    1   | ...
  2   |     1     |    2   | ...
  3   |     1     |    3   | ...
  4   |     2     |    1   | ...
  5   |     2     |    2   | ...

テーブルのすべての従業員エントリは、MSSQL によって自動的に生成される一意の ID (empid) を取得します。従業員の「マスター リスト」を含む CSV ファイルを入力として受け取る PHP アプリケーションがあります。ただし、そのCSVファイルには「empnum」の右側の列しかありません(会社ID、または明らかに従業員IDは含まれていません)。CSV ファイルの各行を繰り返すと、companyid が追加されます。CSVには、まだデータベースにない従業員のみが含まれている必要がありますが、その保証はないため、挿入する前にその従業員がそこにいないことを確認する必要があります。検証方法は、この特定の companyid (たとえば、companyid = 1 に挿入するとします) について、一致する empnum がテーブルにまだ存在しないことを確認することです。したがって、このデータを含む CSV ファイルがあれば、それは有効です。

empnum, ...
4, ...

ただし、このデータを含む CSV ファイルがある場合、それは有効ではありません。

empnum, ...
3, ...

companyid=1 の empnum として 3 がすでに存在するため、ENTIRE のインポートは失敗するはずです。PHP アプリケーションには、次のものがあります。

try {
   db->beginTransaction();
   while (($data = fgetcsv($handle, 5000, ",")) !== FALSE) {
      //SQL TO INSERT ROW   
   }
   db->commit();
} catch (PDO Exception) {
   db->rollBack();
}

その companyid に対して empnum が既に存在する場合に例外が発生するように、行を挿入するにはどの SQL を使用する必要がありますか? どのようなデータベース変更を行う必要がありますか? 私の最初の考えは次のとおりです。

オプション 1 - 一時テーブルに挿入し、companyid/empnum の一致する値で 2 つのテーブルを結合する選択クエリを実行します。0 を超える行が返された場合は、例外をスローします。PRO: 選択は 1 つだけです。CON: すべてが一時テーブルに挿入され、実際のテーブルにダンプされる

オプション 2 - 現在の行に基づいて select ステートメントを実行します。行が 0 を超える場合は例外をスローし、そうでない場合は実際のテーブルに挿入します。PRO: 失敗が発生するとすぐにそれを検出できるため、時間を節約できる可能性があります。CON: クエリが (2x-1) 増加したため、成功すると余分なオーバーヘッドが発生します!

だから私の質問は次のようになります: - 最良の選択肢は何ですか (1、2、またはまったく別のもの)? - 挿入時に MSSQL に例外をスローさせることはできますか?

4

1 に答える 1

1

オプション1は、データをロードする「標準的な」方法です(確かに私の世界では)。一時テーブルは実際には「ステージング」テーブルと呼ばれます。これは、行ごとにチェックする (RBAR を調べる) よりもはるかに高速です。

実際、常に最も時間がかかるのは、行ごとに処理を行うことです。

マッドマップのパフォーマンス比較:

オプション1:

  1. 行ごとにテーブルへの最初の挿入を行います(遅い)
  2. 単一の SELECT クエリでテーブル間の重複をキャプチャ (高速)
  3. 成功した場合は、ステージングをライブ テーブルにコピーします (高速)

オプション 2:

  1. CSV から行ごとにデータをロードします (中)
  2. これを行っている間、キャプチャは毎回選択して行ごとに複製します(遅い)

不明な点は、オプション 2 で重複が見つかった場合にどうするかということです。他のすべてのレコードをロールバックしますか、それともユーザーに通知して続行しますか?

于 2013-03-05T01:05:10.420 に答える