導入 - 準備と実行

導入 - 準備と実行 – SQL 文を準備し、実行する

Description

目的

prepare() execute*() により、 クエリ実行時に性能の向上と柔軟性の向上を得られます。 準備/実行モードは、ひとつの等しいクエリに さまざまな値を投入して何度も実行しなければならない場合 (例えばデータベースへのアドレスリストの追加など) に有用です。

準備/実行モードは、 SQL 構文の異なる複数のデータベースをサポートする際にも有用となります。 INSERT の構文が異なる二種類ののデータベースをサポートする場合を想像してみて下さい。


db1: INSERT INTO tbl_name (col1, col2) VALUES (expr1, expr2)
db2: INSERT INTO tbl_name SET col1=expr1, col2=expr2

スクリプトを複数の文法に対応させるために、 以下のようなクエリを有する配列を作成することが可能です。

<?php
$statement
['db1']['INSERT_PERSON'] = 'INSERT INTO person
    (surname, name, age) VALUES (?, ?, ?)'
;

$statement['db2']['INSERT_PERSON'] = 'INSERT INTO person
    SET surname=?, name=?, age=?'
;
?>

準備

上記の特徴を使用するために、2ステップ進まなければなりません。 ひとつめに命令文を準備することです。 ふたつめはそれを実行することです。

まずはじめに、汎用の SQL 文を prepare() しなければなりません。 汎用の命令文を作成する方法は、通常の SQL クエリを書く際と同様です。

SELECT surname, name, age
    FROM person
    WHERE name = 'name_to_find' AND age < age_limit

次に、実行時に渡されるリテラル値を "プレースホルダ" に置き換えます。

SELECT surname, name, age
    FROM person
    WHERE name = ? AND age < ?

次に、この SQL 文を prepare() に渡し、返される ステートメントハンドルを用いて、 execute() をコールします。

prepare() は、さまざまな型の プレースホルダ (ワイルドカードとも言われる) を処理できます。

  • ? - (推奨されます) 文字列や数値のようなスカラー値を意味します。 データベースの要求に応じ、値のエスケープおよびクォートを 自動的に行います。
  • ! - スカラー値を意味し、"そのまま"命令文に挿入されます。
  • & - 既存のファイル名を要求とし、このファイルの内容を命令文に含まれます。 (例えば、 データベース内にグラフィックファイルのバイナリデータを 保存するといった場合)

それらがプレースホールダーとして解釈されることは望まなければ、 プレースホールダー文字を回避するためにバックスラッシュを使用します。

  UPDATE foo SET col=? WHERE col='over \& under'

実行

命令文を準備した後に、クエリを実行することができます。 これは、準備した文に変数を割り当てることを意味します。 これをするには、 execute() prepare() から返される命令文ハンドル、値を割り当てた配列の 2 つの引数を要求します。

execute() にスカラーを渡す

<?php
// $db という名前の DB オブジェクトが作成済みであると仮定します...
$sth $db->prepare('INSERT INTO numbers (number) VALUES (?)');
$db->execute($sth1);
$db->execute($sth8);
?>

プリペアドステートメントに複数のプレースホルダが含まれる場合は、 その値を配列で execute() に渡さなければなりません。 配列の最初のエントリが最初のプレースホルダを、 ふたつめが 2 番目のプレースホルダを、といったようになります。 その順番は使用されたプレースホルダの型には依存しません。

execute() に配列を渡す

<?php
// $db という名前の DB オブジェクトが作成済みであると仮定します...
$sth $db->prepare('INSERT INTO numbers VALUES (?, ?, ?)');

$data = array(1'one''en');
$db->execute($sth$data);
?>

$data に渡す値は、リテラルである必要があります。 SQL 関数 (例えば CURDATE() など) を渡さないでください。 実行時に処理される SQL 関数は、プリペアドステートメント内に記述する 必要があります。同様に、識別子 (すなわち テーブル名およびカラム名) も渡すことはできません。なぜなら、それらの名前は準備の段階で 検証されるものだからです。

複数回の実行

DB には、複数のクエリを一度に実行する機能が含まれています。 それらを手動で実行するかわりに、以下のようにします。

execute() に配列を渡す

<?php
// $db という名前の DB オブジェクトが作成済みであると仮定します...
$alldata = array(array(1'one''en'),
                 array(
2'two''to'),
                 array(
3'three''tre'),
                 array(
4'four''fire'));
$sth $db->prepare('INSERT INTO numbers VALUES (?, ?, ?)');
foreach (
$alldata as $row) {
    
$db->execute($sth$row);
}
?>

これは、4 件のクエリを発行します。

INSERT INTO numbers VALUES ('1', 'one', 'en')
INSERT INTO numbers VALUES ('2', 'two', 'to')
INSERT INTO numbers VALUES ('3', 'three', 'tre')
INSERT INTO numbers VALUES ('4', 'four', 'fire')

上の例のように foreach を明示的に行うことを避けるため、 executeMultiple() を使用することができます。

execute()の代わりに executeMultiple()を使用する

<?php
// $db という名前の DB オブジェクトが作成済みであると仮定します...
$alldata = array(array(1'one''en'),
                 array(
2'two''to'),
                 array(
3'three''tre'),
                 array(
4'four''fire'));
$sth $db->prepare('INSERT INTO numbers VALUES (?, ?, ?)');
$db->executeMultiple($sth$alldata);
?>

結果は同じです。 もしレコードの1つが失敗した場合、未実行のクエリは実行されません。

execute*() の返す値は、以下の 3 種類です。 結果を返すクエリ (例えば SELECT クエリなど) の場合は新しい DB_result オブジェクト、 データを操作するクエリ (例えば INSERT クエリなど) の場合は DB_OK、 あるいは失敗した場合には DB_Error オブジェクトを返します。

クエリ結果からデータを取得する (Previous) SQL 文を自動で組み立て、実行する (Next)
Last updated: Sun, 23 Nov 2014 — Download Documentation
Do you think that something on this page is wrong? Please file a bug report or add a note.
View this page in:

User Notes:

There are no user contributed notes for this page.