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でseqとcodeみたいなものをあわせて ユニークキーをはりたかった。 ...
-
-
ON DUPLICATE KEY UPDATE後にinsert_idを取得すると結果が0になる
MySQLでON DUPLICATE KEY UPDATE句指定し、データの登録 ...
-
-
MySQLでROW_NUMBER関数を使用してグループ毎に連番を設定する方法
以前にMySQLでオートインクリメントを使用せずにグループ毎に連番を設定する方法 ...
-
-
MySQLでストアドプロシージャ戻り値対応版であるストアドファンクションの設定と利用方法
先日MySQLのストアドプロシージャに関するメモを書いたが、今回はストアドファン ...
-
-
MySQLでtext型カラムに入っている数値をint型としてソートする
MySQLでtext型として指定されているカラムがあり、その中には文字列であった ...