さらに多くの成熟したデータベースが、準備されたステートメントの概念をサポートしています。準備されたステートメントとは何ですか?これは、実行する SQL のコンパイルされたテンプレートと考えてください。変数パラメーターを使用してカスタマイズできます。プリペアドステートメントには 2 つの大きな利点があります:
クエリは 1 回解析 (または前処理) するだけで済みますが、同じまたは異なるパラメーターを使用して複数回実行できます。クエリの準備が完了すると、データベースはクエリを実行するための計画を分析、コンパイル、最適化します。複雑なクエリの場合、このプロセスには時間がかかり、同じクエリを異なるパラメータで複数回繰り返す必要がある場合、アプリケーションの速度が大幅に低下する可能性があります。準備されたステートメントを使用すると、分析/コンパイル/最適化サイクルの繰り返しを回避できます。簡単に言えば、準備されたステートメントは使用するリソースが少ないため、より高速に実行されます。
準備されたステートメントに指定されたパラメーターを引用符で囲む必要はありません。ドライバーが自動的に処理します。アプリケーションでプリペアド ステートメントのみを使用する場合、SQL インジェクションは確実に発生しません。 (ただし、クエリの他の部分がエスケープされていない入力から構築されている場合は、依然として SQL インジェクションのリスクが存在します)。
準備されたステートメントは非常に便利ですが、その唯一の機能は、ドライバーがサポートしていない場合に PDO が処理をシミュレートすることです。これにより、データベースにそのような機能があるかどうかに関係なく、アプリケーションは同じデータ アクセス パターンを使用できるようになります。
例 #1 繰り返し挿入に準備済みステートメントを使用する
次の例では、対応する名前付きプレースホルダーを名前と値で置き換えることによって挿入クエリを実行します
<?php $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); $stmt->bindParam(':name', $name); $stmt->bindParam(':value', $value); // 插入一行 $name = 'one'; $value = 1; $stmt->execute(); // 用不同的值插入另一行 $name = 'two'; $value = 2; $stmt->execute(); ?>
例 #2 繰り返し挿入に準備済みステートメントを使用する
以下の例 挿入クエリを実行する? プレースホルダーを名前と値に置き換えます。
<?php $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)"); $stmt->bindParam(1, $name); $stmt->bindParam(2, $value); // 插入一行 $name = 'one'; $value = 1; $stmt->execute(); // 用不同的值插入另一行 $name = 'two'; $value = 2; $stmt->execute(); ?>
例 #3 準備されたステートメントを使用してデータを取得する
次の例では、指定された形式のキー値に基づいてデータを取得します。ユーザー入力は自動的に引用されるため、SQL インジェクション攻撃の危険はありません。
<?php $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?"); if ($stmt->execute(array($_GET['name']))) { while ($row = $stmt->fetch()) { print_r($row); } } ?>
データベース ドライバーがサポートしている場合、アプリケーションは出力パラメーターと入力パラメーターをバインドすることもできます。出力パラメーターは通常、ストアド プロシージャから値を取得するために使用されます。出力パラメータをバインドするときに、指定されたパラメータの長さを知っておく必要があるため、出力パラメータの使用は入力パラメータよりも少し複雑です。パラメータにバインドされた値が推奨される長さを超える場合、エラーが生成されます。
例 #4 出力パラメーターを使用したストアド プロシージャの呼び出し
<?php $stmt = $dbh->prepare("CALL sp_returns_string(?)"); $stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000); // 调用存储过程 $stmt->execute(); print "procedure returned $return_value\n"; ?>
入力値と出力値の両方を使用してパラメーターを指定することもでき、構文は出力パラメーターと似ています。次の例では、文字列「hello」がストアド プロシージャに渡され、ストアド プロシージャが返されるときに、hello がストアド プロシージャによって返された値に置き換えられます。
例 #5 入出力パラメーターを使用したストアド プロシージャの呼び出し
<?php $stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)"); $value = 'hello'; $stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000); // 调用存储过程 $stmt->execute(); print "procedure returned $value\n"; ?>
例 #6 プレースホルダーの無効な使用
<?php $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'"); $stmt->execute(array($_GET['name'])); // 占位符必须被用在整个值的位置 $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?"); $stmt->execute(array("%$_GET[name]%")); ?>