プリペアドステートメント

広告

例えば何行ものデータを挿入する場合を考えて見ます。値だけ異なるようなSQL文を何度も実行する場合、プリペアドステートメントを使うと便利です。

プリペアドステートメントを使う場合には"query"メソッドの代わりにDB_commonクラスで用意されている"prepare"メソッドを使います。

execute() で実行できるように、SQL 文を 準備します。

パラメータ:
  string $query  準備するクエリ。
返り値:
  resource - クエリのハンドル、あるいは失敗した場合に DB_Error オブ
    ジェクトを返します。

使い方は"query"メソッドでプレースホルダーを使った場合と同じです。何度も繰り返し使われるSQL文の中で、毎回異なる値の部分を「?」で置き換えて指定します。

$sql = "insert into shouhin (id, name) VALUES (?, ?)";
$stmt = $db->prepare($sql);

これでベースとなるSQL文が出来ましたので、次はプレースホルダー部分の値を指定して実行します。DB_commonクラスで用意されている"execute"メソッドを使います。

prepare() で指定した SQL 文に $data の情報を適用し、クエリをデータベース
に送信します。

パラメータ:
  resource $stmt  prepare() が返すクエリハンドル。
  mixed $data  プリペアドステートメントに適用する配列・文字列あるい
    は数値のデータ。渡す項目数は、文中のプレースホルダの数と一致し
    ていなければなりません。プレースホルダがひとつだけの場合は配列
    でない値を指定し、複数存在する場合は個々の値を要素にもつ配列を
    指定します。
返り値:
  結果を返すクエリ (例えば SELECT クエリなど) の場合は新しい 
    DB_result オブジェクト、データを操作するクエリ (例えば INSERT
    クエリなど) の場合は DB_OK、あるいは失敗した場合には DB_Error
    オブジェクトを返します。

プレースホルダーで置き換えておいた部分に実際に当てはめたい値を指定します。1つの値であれば単に値を指定し、2つ以上ある場合は配列の形にして指定します。

$sql = "insert into shouhin (id, name) VALUES (?, ?)";
$stmt = $db->prepare($sql);

$data = array(1, 'エアコン');
$db->execute($stmt, $data);

同じSQL文をベースにして何度も実行する場合は"execute"メソッドだけを繰り返し使用します。

$sql = "insert into shouhin (id, name) VALUES (?, ?)";
$stmt = $db->prepare($sql);

$data = array(1, 'エアコン');
$db->execute($stmt, $data);

$data = array(2, 'パソコン');
$db->execute($stmt, $data);

$data = array(3, 'テレビ');
$db->execute($stmt, $data);

サンプルプログラム

では実際に試してみます。

sample12-1.php

<html>
<head><title>PHP TEST</title></head>
<body>

<?php

require_once 'DB.php';

$dsn = 'mysqli://testuser:testuser@localhost/uriage';

$db = DB::connect($dsn);
if (PEAR::isError($db)) {
    die($db->getMessage());
}

print('接続に成功しました<br>');

$db->query('SET NAMES sjis');
if (PEAR::isError($db)) {
    die($db->getMessage());
}

$sql = 'select * from shouhin';
$res =& $db->query($sql);
if (PEAR::isError($res)) {
    die($res->getMessage());
}

while ($row =& $res->fetchRow(DB_FETCHMODE_OBJECT)){
    print($row->id);
    print($row->name.'<br>');
}

print('<br>データを追加します。<br><br>');

$sql = "insert into shouhin (id, name) VALUES (?, ?)";
$stmt = $db->prepare($sql);
if (PEAR::isError($res)) {
    die($res->getMessage());
}

$data = array(6, 'エアコン');
$db->execute($stmt, $data);
if (PEAR::isError($res)) {
    die($res->getMessage());
}

$data = array(7, '扇風機');
$db->execute($stmt, $data);
if (PEAR::isError($res)) {
    die($res->getMessage());
}

$data = array(8, '空気清浄機');
$db->execute($stmt, $data);
if (PEAR::isError($res)) {
    die($res->getMessage());
}

print('<br>追加後のデータを取得します。<br><br>');

$sql = 'select * from shouhin';
$res =& $db->query($sql);
if (PEAR::isError($res)) {
    die($res->getMessage());
}

while ($row =& $res->fetchRow(DB_FETCHMODE_OBJECT)){
    print($row->id);
    print($row->name.'<br>');
}

$db->disconnect();

?>

</body>
</html>

上記をWWWサーバに設置しブラウザで見てみると下記のようなりました。

PEAR::DBでプリペアドステートメント

( Written by Tatsuo Ikura )