📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| 186行目: | 186行目: | ||
<u>自動的にロールバックが行われる時は、<code>PDO::beginTransaction</code>メソッドを実行した場合のみである。</u><br> | <u>自動的にロールバックが行われる時は、<code>PDO::beginTransaction</code>メソッドを実行した場合のみである。</u><br> | ||
<u>トランザクションを開始するクエリを手動で発行した場合、PDOはそれを知ることができないため、問題が発生してもロールバックできない。</u><br> | <u>トランザクションを開始するクエリを手動で発行した場合、PDOはそれを知ることができないため、問題が発生してもロールバックできない。</u><br> | ||
<br><br> | |||
== プリペアドステートメントおよびストアドプロシージャ == | |||
プリペアドステートメントとは、実行するSQLをコンパイルしたテンプレートのようなものである。<br> | |||
パラメータ変数を使用することで、SQLをカスタマイズすることができる。<br> | |||
<br> | |||
プリペアドステートメントには、以下に示す2つの大きな利点がある。<br> | |||
* 一般的に、クエリを実行する時、クエリの解析、コンパイル、実行プランの最適化が行われる。<br>プリペアドステートメントを使用する場合、これらの解析、コンパイル、最適化の繰り返しを避けることができる。<br>端的に言うと、プリペアドステートメントは使用するリソースが少ないため、高速に動作するということである。<br><br> | |||
* プリペアドステートメントに渡すパラメータは、引用符で括る必要は無く、ドライバが自動的に行う。<br>プリペアドステートメントでは、SQLインジェクションは発生しない。 | |||
<br> | |||
プリペアドステートメントは、データベースの種類や機能に関わらず同じ仕組みで データベースへのアクセスができる。<br> | |||
<br> | |||
==== Insert (1)==== | |||
以下の例では、nameおよびvalueを名前付きプレースホルダで置き換えて、INSERT句を実行する。<br> | |||
<syntaxhighlight lang="php"> | |||
<?php | |||
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); | |||
$stmt->bindParam(':name', $name); | |||
$stmt->bindParam(':value', $value); | |||
// 1レコード目の挿入 | |||
$name = 'one'; | |||
$value = 1; | |||
$stmt->execute(); | |||
// パラメータを変更して、2レコード目の挿入 | |||
$name = 'two'; | |||
$value = 2; | |||
$stmt->execute(); | |||
?> | |||
</syntaxhighlight> | |||
<br> | |||
==== Insert (2) ==== | |||
以下の例では、nameおよびvalueをプレースホルダ<code>?</code>で置き換えて、INSERT句を実行する。<br> | |||
<syntaxhighlight lang="php"> | |||
<?php | |||
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)"); | |||
$stmt->bindParam(1, $name); | |||
$stmt->bindParam(2, $value); | |||
// 1レコード目の挿入 | |||
$name = 'one'; | |||
$value = 1; | |||
$stmt->execute(); | |||
// パラメータを変更して、2レコード目の挿入 | |||
$name = 'two'; | |||
$value = 2; | |||
$stmt->execute(); | |||
?> | |||
</syntaxhighlight> | |||
<br> | |||
==== SELECT ==== | |||
以下の例では、フォームで入力したキーの値に応じたデータを取得している。<br> | |||
ユーザの入力内容は自動的に引用符で括られるため、SQLインジェクション攻撃の恐れは無い。<br> | |||
<syntaxhighlight lang="php"> | |||
<?php | |||
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?"); | |||
if($stmt->execute(array($_GET['name']))) | |||
{ | |||
while($row = $stmt->fetch()) | |||
{ | |||
print_r($row); | |||
} | |||
} | |||
?> | |||
</syntaxhighlight> | |||
<br> | |||
==== ストアドプロシージャの呼び出し : 出力パラメータの指定 ==== | |||
データベースドライバがサポートしている時、入力パラメータだけでなく、出力パラメータもバインドすることが可能である。<br> | |||
<br> | |||
出力パラメータは、ストアドプロシージャから値を取得するために使用する。<br> | |||
この場合、返される値の大きさがどの程度になるのかをバインド時に知る必要がある。<br> | |||
指定した大きさよりも大きな値が返される場合は、エラーが発生する。<br> | |||
<syntaxhighlight lang="php"> | |||
<?php | |||
$stmt = $dbh->prepare("CALL sp_returns_string(?)"); | |||
$stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000); | |||
// ストアドプロシージャを呼び出す | |||
$stmt->execute(); | |||
print "プロシージャが返した値は $return_value です\n"; | |||
?> | |||
</syntaxhighlight> | |||
<br> | |||
==== ストアドプロシージャの呼び出し : 入出力パラメータの指定 ==== | |||
入出力の両方に使用するパラメータを指定することもできる。<br> | |||
入出力パラメータの書式は、出力パラメータと同じである。<br> | |||
<br> | |||
以下の例では、ストアドプロシージャに文字列'hello'を渡している。<br> | |||
プロシージャの結果が返ってくると、文字列'hello'はプロシージャの返す値に置き換えられる。<br> | |||
<syntaxhighlight lang="php"> | |||
<?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 "プロシージャが返した値は $value です\n"; | |||
?> | |||
</syntaxhighlight> | |||
<br> | |||
==== プレースホルダの間違った使用例 ==== | |||
<syntaxhighlight lang="php"> | |||
<?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]%")); | |||
?> | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:Web]] | [[カテゴリ:Web]] | ||