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のトリガーを使用して特定のテーブルの操作を行った際に別テーブルにログを残す方法
MySQLにトリガーという機能があるらしくどのようなものか調べたところ、事前に「 ...
-
MySQLで同一サーバーの異なるDB内のテーブルをJOINする
同一のMySQLサーバーでdb1データベースのtable1テーブルと、db2デー ...
-
adminerでMySQLに接続しようとするとエラーになる場合の対応方法
新しく構築したサーバにadminerを入れて接続しようとすると、「mysqlnd ...
-
PLESK利用時にMySQLでrootのパスワードが分からない場合の対応方法
pleskで管理しているサーバがあり、mysqlのrootのパスワードが分からな ...
-
MySQLでスレッドの実行状況を表示しスレッドの経過時間チェックや特定スレッドを強制終了する方法
データベースサーバが重たく、原因を調査する機会があった。サーバ自体のメモリやCP ...