2012-05-10 2 views
1

以下のようなコードを使用してmysql DBに挿入します(PDOを使用しています)。 目的は1つのクエリのみを使用してデータを挿入することでした。 残念ながら、PDOはbindValueやparamを使用しないため、PDOを使用する目的が無効になります。私はコードが安全であるように書くが、不要なクエリは避けたい。 誰もこれを行う方法をお勧めできますか?不要なクエリを回避しながらPDOを使用してこれを行うより安全な方法はありますか?

注1:セット内の質問の数は、プログラムにアクセスするたびに変わる可能性があります(実行するたびに$totalQが異なる場合があります)。

try 
{ 
    for ($i=0; $i<$totalQ; $i++) 
    { 
     $stqid[$i][0]=$lastInsertValue;  //instance   PDO::PARAM_INT 
     $stqid[$i][1]=$jqid[$i][0];   //question number PDO::PARAM_INT 
     $stqid[$i][2]=$jqid[$i][5];   //result   PDO::PARAM_INT 
     $stqid[$i][3]=$jqid[$i][3];   //question start PDO::PARAM_STR 
     $stqid[$i][4]=$jqid[$i][4];   //question finish PDO::PARAM_STR 
    } 

    $values = array(); 
    foreach ($stqid as $rowValues) 
    { 
     foreach ($rowValues as $key => $rowValue) 
     { 
      $rowValues[$key] = $rowValues[$key]; 
     } 

     $values[] = "(" . implode(', ', $rowValues) . ")"; 
    } 

    $count = $dbh->exec("INSERT INTO results(instance, qid, result, start, finish) VALUES ".implode (', ', $values)); 
    $dbh = null; 
} 

注2:開始と終了の時間形式でコンマが破文でエラーが発生する可能性があります。私はそれらを追加して、あなたが達成しようとしているものを見ることができます。

ご協力いただければ幸いです。ありがとう。

編集:私はクリスの答えを選んだが、Alix Axelは彼の助言に非常に感謝している。それは、多くの助け、ありがとう!

+2

あなたはあなたが必要なだけのプレースホルダを追加して、ちょうどプリペアドステートメントを使用して、ちょうど別の値でそれを実行しないのはなぜ、それら – zerkms

+1

に値をバインドすることができますか?私はこれをテストしていませんが、パフォーマンスの影響はそれほど劇的ではないと思います。私は間違っているかもしれない。 –

+0

私はPDOに本当に苦労します。おそらく例にリンクできますか? – TryHarder

答えて

2

未テスト。準備されたステートメントを使用します。

$numColumns = 5; //or $numColumns = count($stqid[0]); 
$rowPlaceholder = join(', ', array_fill(0, $numColumns, '?')); 
$rowPlaceholders = array_fill(0, $totalQ, "($rowPlaceholder)"); 
echo $sql = "INSERT INTO results(instance, qid, result, start, finish) VALUES " . join(", \n", $rowPlaceholders); 
$flat = call_user_func_array('array_merge', $stqid); 
$stmt = $dbh->prepare($sql); 
$stmt->execute($flat); 
+0

'$ flat = call_user_func_array( 'array_merge'、$ stqid);'そうですか? –

+1

はい、2次元配列を平坦化します。http://codepad.org/7oDB8YOz – goat

+0

実際、私の+1。 –

2

どのようにこのようなものについて:

try 
{ 
    for ($i=0; $i<$totalQ; $i++) 
    { 
     $stqid[$i][0]=$lastInsertValue;  //instance   PDO::PARAM_INT 
     $stqid[$i][1]=$jaid[$i][0];   //question number PDO::PARAM_INT 
     $stqid[$i][2]=$jaid[$i][5];   //result   PDO::PARAM_INT 
     $stqid[$i][3]=$jqid[$i][3];   //question start PDO::PARAM_STR 
     $stqid[$i][4]=$jqid[$i][4];   //question finish PDO::PARAM_STR 
    } 

    $values = null; 

    foreach ($stqid as $rowValues) 
    { 
     $values .= vsprintf('(%s, %s, %s, %s, %s) ', array_map(array($dbh, 'quote'), $rowValues)); 
    } 

    $count = $dbh->exec('INSERT INTO results (instance, qid, result, start, finish) VALUES ' . rtrim($values) . ';'); 
    $dbh = null; 
} 
+0

あなたの答えをありがとう。私は、vsprintfを使用して、開始時刻と終了時刻のコンマに関連付けられたエラーを回避することを推測しています。これはそれをより安全にしますか? – TryHarder

+1

@moomoochoo:いいえ、私は '[v] sprintf'を使用しました。なぜなら、あなたは常に5つのプレースホルダーを持っていて、'、 'で埋め込むよりも信頼性が高いからです。最初の 'PDO :: quote()'はすべての引数(これはSQLインジェクション攻撃を止めるのに十分です)に入ると、 'vsprintf'は最初の3つの引数を整数にキャストします。かなり防弾です。 –

+0

詳細な説明ありがとうございます!今私はそれをはるかに良く理解しています。 – TryHarder

関連する問題