導入 - 準備と実行

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

説明

目的

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

準備/実行モードは、 SQL 構文の異なる複数のデータベースをサポートする際にも有用となります。 INSERT の構文が異なる二種類ののデータベースをサポートする場合を想像してみて下さい。
db1: INSERT INTO tbl_name (col1, col2) VALUES (expr1, expr2)
db2: INSERT INTO tbl_name SET col1=expr1, col2=expr2
スクリプトを複数の文法に対応させるために、 以下のようなクエリを有する配列を作成することが可能です。
$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() に渡さなければなりません。 配列の最初のエントリが最初のプレースホルダを、 ふたつめが 2 番目のプレースホルダを、といったようになります。 その順番は使用されたプレースホルダの型には依存しません。

警告

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

複数回の実行

DB には、複数のクエリを一度に実行する機能が含まれています。 それらを手動で実行するかわりに、以下のようにします。
これは、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() を使用することができます。

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

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