2017-01-03 9 views
1

PHPバージョン5.3.3、mysql 5.0.95PHP mysqli_multi_query whileループのトランザクション

既存のテーブルから2つの同一のテーブルにデータを移行する必要があります。オリジナルのデータは、2つの新しいテーブルに挿入する前に解析する必要があります。 (このコードは、この問題を切り分けるためには表示されていません。) トランザクションを使用して、新しいテーブルが同一であることを確認したい。

task_idフィールドはtest_timecardにautoincrementであり、test_timecar_2ではunsigned mediumintです。

エンジンは両方のテーブルのInnoDBです。

別々のクエリが動作します:mysqli_multi_queryと

$timecard_data_results = array(); 
$fill_old_data_array_def = " SELECT task_id, company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment FROM timecard WHERE company_id = '" . $company_request . "' AND employee_id = '" . $employee_request . "' AND DATE(task_start_time) < '" . $new_text_format_date . "' AND (DATE(task_end_time) > '2014-12-31' OR DATE(task_end_time) = '2000-01-01') ORDER BY task_start_time"; 
$timecard_data_results = mysqli_query($conn, $fill_old_data_array_def); 

while($timecard_record = mysqli_fetch_assoc($timecard_data_results)) { 

    $company_id = $timecard_record['company_id']; 
    $employee_id = $timecard_record['employee_id']; 
    $location = $timecard_record['location']; 
    $task_name = $timecard_record['task_name']; 
    $task_start_time = $timecard_record['task_start_time']; 
    $task_end_time = $timecard_record['task_end_time']; 
    $tccomment = $timecard_record['tccomment']; 

    $troubleshoot_def = "INSERT INTO test_timecard (company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment) VALUES ('" . $company_id . "', '" . $employee_id . "', '" . $location . "', '" . $task_name . "', '" . $task_start_time . "', '" . $task_end_time . "', '" . $tccomment . "')"; 
    $troubleshoot_2_def = "INSERT INTO test_timecard_2 (task_id, company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment) VALUES (LAST_INSERT_ID(), '" . $company_id . "', '" . $employee_id . "', '" . $location . "', '" . $task_name . "', '" . $task_start_time . "', '" . $task_end_time . "', '" . $tccomment . "')";  
    $troubleshoot = mysqli_query ($conn, $troubleshoot_def); 
    $troubleshoot_2 = mysqli_query ($conn, $troubleshoot_2_def); 
} 

の取引のみの両方のテーブルに1行を挿入します。エラーは報告されていません。

$timecard_data_results = array(); 
$fill_old_data_array_def = " SELECT task_id, company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment FROM timecard WHERE company_id = '" . $company_request . "' AND employee_id = '" . $employee_request . "' AND DATE(task_start_time) < '" . $new_text_format_date . "' AND (DATE(task_end_time) > '2014-12-31' OR DATE(task_end_time) = '2000-01-01') ORDER BY task_start_time"; 
$timecard_data_results = mysqli_query($conn, $fill_old_data_array_def); 

while($timecard_record = mysqli_fetch_assoc($timecard_data_results)) { 

    $company_id = $timecard_record['company_id']; 
    $employee_id = $timecard_record['employee_id']; 
    $location = $timecard_record['location']; 
    $task_name = $timecard_record['task_name']; 
    $task_start_time = $timecard_record['task_start_time']; 
    $task_end_time = $timecard_record['task_end_time']; 
    $tccomment = $timecard_record['tccomment']; 

    $troubleshoot_def = "START TRANSACTION; INSERT INTO test_timecard (company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment) VALUES ('" . $company_id . "', '" . $employee_id . "', '" . $location . "', '" . $task_name . "', '" . $task_start_time . "', '" . $task_end_time . "', '" . $tccomment . "'); INSERT INTO test_timecard_2 (task_id, company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment) VALUES (LAST_INSERT_ID(), '" . $company_id . "', '" . $employee_id . "', '" . $location . "', '" . $task_name . "', '" . $task_start_time . "', '" . $task_end_time . "', '" . $tccomment . "'); COMMIT;"; 
    $troubleshoot = mysqli_multi_query ($conn, $troubleshoot_def); 
}  

Stumped。

+0

(上記コードの二つの部分からわずかコピーペーストである)右の列を取得するために世話をする)、それだけで呼ばれるべき(ループ外で)一度、すべてのINSERT文が連結されます。これはまた、START TRANSACTIONはループの前に移動し、ループの後にCOMMITする必要がありますが、実際には必要ではありません。問合せ文字列をエコーし​​て、すべての目的の文が移入されたことを確認します。次の関連する質問も確認してください。http://stackoverflow.com/q/20143592/2298301 –

答えて

0
$troubleshoot_def = "INSERT INTO test_timecard (company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment) VALUES ('" . $company_id . "', '" . $employee_id . "', '" . $location . "', '" . $task_name . "', '" . $task_start_time . "', '" . $task_end_time . "', '" . $tccomment . "')"; 
    $troubleshoot_2_def = "INSERT INTO test_timecard_2 (task_id, company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment) VALUES (LAST_INSERT_ID(), '" . $company_id . "', '" . $employee_id . "', '" . $location . "', '" . $task_name . "', '" . $task_start_time . "', '" . $task_end_time . "', '" . $tccomment . "')";  

ここには多くの問題があります。第一に、ほぼ同一のデータを2つの異なるテーブルに挿入することはまったく意味がありません。実際に操作が完了すると、ほとんど同じデータを持つ3つのテーブルがあります。つまり、test_timecard_2,とtimecard

2番目にエスケープされていないデータを挿入しています。データは別のテーブルから取得されるため、SQLインジェクションの可能性はあまりありませんが、依然としてクエリが失敗する可能性があります。具体的に私はこのようなコードについて話しています:

VALUES ('" . $company_id . "', '" . $employee_id . "', '" . $location . "', '" . $task_name . "', '" . $task_start_time . "', '" . $task_end_time . "', '" . $tccomment . "')"; 

第三に、あなたがSELECT行う必要があることはほとんどない - MySQLはINSERT SELECTコマンドが組み込まれていますので、INSERT - LOOPを。

INSERT INTO test_timecard (company_id, employee_id, location, task_name, task_start_time, task_end_time, tccomment) 
SELECT * FROM time_card 

あなたは(mysqli_multi_queryを使用するつもりなら

+0

誤解を招くような申し立て。子テーブルには、実際に親テーブルに存在しないいくつかの追加のフィールドがあります。つまり、元のデータを解析するwhileループです。私はトランザクションの問題に遭遇したとき、私は私の質問で他のコードの気を散らすことなく、そのsnafuを分離しようとしました。新しいテーブルを作成することは、1回限りの手順であり、完全に社内で行われるため、注入に関する懸念はほとんどありません。 – dirk

+0

いくつかの追加フィールドは、余分なテーブルを作成するのに十分な理由ではありません。これは、すべてのデータベース正規化プリンシパルに違反しています。 – e4c5

+0

余分なテーブルを脇に置いておくと、これを行う正しい方法は、単一のINSERT SELECT文を使用することです。あなたのテーブルのサイズに応じて数千から数百万のインサートになるかもしれないものの代わりに – e4c5