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で「server has gone~」というエラーの対応方法
MySQLで「MySQL server has gone away」というエラー ...
-
MySQLでWhere句をつけてdumpファイルを出力する方法
MySQLであるテーブルからWhere句をつけて、絞った結果をダンプさせたかった ...
-
PHPからMySQLにシリアライズしたデータを格納
アンケートフォームみたいなのがあって、 今後も定期開催し、尚且つ質問内容は増減す ...
-
MySQLのREGEXPで半角記号を検索したい場合の対応方法
MySQLのREGEXPで半角記号を検索したい場合\\を付けてエスケープしないと ...
-
MySQLのtinyintのカラムにbool値を入れた場合
他所のシステムに携わることがあり中身を色々見ているとMySQLでtinyint( ...