PHPでmysqli関数使用時のプリペアドステートメントの利用方法
PHPでMySQLを扱う際はmysqli関数を、エスケープの際はreal_escape_stringを使用していた。ただ他社のソースコードを見るとpdo / mysqliどちらを使うにしてもプリペアドステートメントで書かれていることが多いように思う。そこでプリペアドステートメントの書き方を覚えておきたい。
データベース構造
mysql> SHOW COLUMNS FROM test_table; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | score | int | NO | | NULL | | | regist_ymd | datetime | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+
ソースコード
INSERT
$stmt = $mysqli->prepare("
INSERT INTO test_table
(name, score, regist_ymd)
VALUES
(?, ?, now())
");
$name = '山田';
$score = 50;
$stmt->bind_param('si', $name, $score);
$res = $stmt->execute();
$stmt->close();
UPDATE
$stmt = $mysqli->prepare("
UPDATE test_table
SET name = ?
WHERE id = ?
");
$name = '高橋';
$id = 1;
$stmt->bind_param('si', $name, $id);
$res = $stmt->execute();
$stmt->close();
SELECT
$stmt = $mysqli->prepare("
SELECT *
FROM test_table
WHERE score > ?
");
$score = 70;
$stmt->bind_param('i',$score);
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_array(MYSQLI_ASSOC)){
var_dump($row);
}
DELETE
$stmt = $mysqli->prepare("
DELETE FROM test_table
WHERE id = ?
");
$id = 1;
$stmt->bind_param('i', $id);
$res = $stmt->execute();
$stmt->close();
解説等
bind_param
第1引数にバインド変数の型を記述する必要あり。型指定文字は以下の通り。
- i → int
- d → float
- s → string
- b → blob
バインドする変数が「文字列、数値、文字列」の場合は「sis」のように記述する。
execute
プリペアドステートメントの実行。成否により戻り値がtrue / falseになるのでエラーチェックの際は「if( $stmt->execute() )」とかになりそう。
エラー対応
Fatal error: Uncaught mysqli_sql_exception: Unknown column 'xxx' in 'field list' in
(カラム名が間違っている等で)カラムが見つからない場合に発生するエラー。例えばだけど今回の場合「score」というカラムを「point」とかで書いちゃうとエラー。
カラム名に間違いが無いか確認すること。
Fatal error: Uncaught mysqli_sql_exception: Column count doesn't match value count at row
バインド変数とカラム数が合わない場合に発生するエラー。どちらかに抜けが無いか確認すること。
プリペアドステートメントのメリット
エスケープが不要
公式案内にも書かれているようにエスケープが不要になる。
キャッシュが効くので実行速度アップ
MySQL側でキャッシュが効くようになり、実行速度アップが見込める。
関連記事
-
-
MySQLでIPを整数値としてカラムに格納する
MySQLでIPを整数値としてカラムに格納しているケースがあった。今までIPが必 ...
-
-
MySQLで特定のテーブルにパーティショニング設定し高速化を図る方法
以前に他社が設計されたログ系のテーブルを拝見した際にパーティショニング設定が行わ ...
-
-
MySQLでテーブル構造とデータをコピーする方法
MySQLで既にあるテーブルとデータに対して実験を行う必要があった。本番テーブル ...
-
-
MySQLで「server has gone~」というエラーの対応方法
MySQLで「MySQL server has gone away」というエラー ...
-
-
MySQLで全国の市区町村のデータを入手し、抽出する方法
都道府県と市区町村が連携したセレクトメニューを作成したかった。具体的には大阪府を ...