ほぼすべての「PHP内からSQLを実行するにはどうすればよいですか」の質問と同様に、本当に プリペアドステートメントを使用する必要があります。それほど難しいことではありません:
$ids = array(2, 4, 6, 8);
// prepare an SQL statement with a single parameter placeholder
$sql = "UPDATE MyTable SET LastUpdated = GETDATE() WHERE id = ?";
$stmt = $mysqli->prepare($sql);
// bind a different value to the placeholder with each execution
for ($i = 0; $i < count($ids); $i++)
{
$stmt->bind_param("i", $ids[$i]);
$stmt->execute();
echo "Updated record ID: $id\n";
}
// done
$stmt->close();
または、次のようにすることもできます:
$ids = array(2, 4, 6, 8);
// prepare an SQL statement with multiple parameter placeholders
$params = implode(",", array_fill(0, count($ids), "?"));
$sql = "UPDATE MyTable SET LastUpdated = GETDATE() WHERE id IN ($params)";
$stmt = $mysqli->prepare($sql);
// dynamic call of mysqli_stmt::bind_param hard-coded eqivalent
$types = str_repeat("i", count($ids)); // "iiii"
$args = array_merge(array($types), $ids); // ["iiii", 2, 4, 6, 8]
call_user_func_array(array($stmt, 'bind_param'), ref($args)); // $stmt->bind_param("iiii", 2, 4, 6, 8)
// execute the query for all input values in one step
$stmt->execute();
// done
$stmt->close();
echo "Updated record IDs: " . implode("," $ids) ."\n";
// ----------------------------------------------------------------------------------
// helper function to turn an array of values into an array of value references
// necessary because mysqli_stmt::bind_param needs value refereces for no good reason
function ref($arr) {
$refs = array();
foreach ($arr as $key => $val) $refs[$key] = &$arr[$key];
return $refs;
}
必要に応じて、他のフィールドのパラメータプレースホルダーを追加します。
どれを選びますか?
-
最初のバリアントは、可変数のレコードを繰り返し処理し、データベースに複数回アクセスします。これは、UPDATEおよびINSERT操作に最も役立ちます。
-
2番目のバリアントは、可変数のレコードでも機能しますが、データベースにヒットするのは1回だけです。これは反復アプローチよりもはるかに効率的です。明らかに、影響を受けるすべてのレコードに対して同じことしか実行できません。これは、SELECTおよびDELETE操作の場合、または同じデータで複数のレコードを更新する場合に最も役立ちます。
なぜステートメントを準備するのですか?
- プリペアドステートメントは、SQLインジェクション攻撃を不可能にするため、はるかに安全です。これが、プリペアドステートメントを使用する主な理由です。入るのに賢明な習慣は次のとおりです。「本当に必要ではない」と思ったとしても、常に準備されたステートメントを使用してください。ネグレクトがやって来て、あなた(またはあなたの顧客)を噛みます。
- 同じプリペアドステートメントを異なるパラメータ値で複数回再利用する方が、複数の完全なSQL文字列をデータベースに送信するよりも効率的です。これは、データベースがステートメントを1回コンパイルするだけで、再利用できるためです。
-
execute()
では、パラメータ値のみがデータベースに送信されます 、したがって、繰り返し使用する場合に必要なデータが少なくなります。
より長いループでは、プリペアドステートメントを使用することとプレーンSQLを送信することの間の実行時間の違いが顕著になります。