複数クエリをPHPの mysqli を使って実行したい場合・・・
普通に mysqli::query ( mysqli_query ) 関数は使えません。
あと複数クエリを実行するなら、注意しないといけないこともあります。
ということで過去の自分の経験を踏まえ、
PHPの mysqli で複数クエリを実行する方法&コード例をまとめました。
このページの目次
mysqli::query 関数だと単体のSQL文しか実行できない
普通PHPでSQLを実行するなら、 mysqli::query を使うと思います。
でもこれって単体のクエリしか実行できないんです。
例えば・・・次みたいなSQLをコードから実行してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/// 複数クエリ $sql = " CREATE TABLE IF NOT EXISTS players ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), score BIGINT ); INSERT INTO players (name, score) VALUES ('hoge', 256), ('fuga', 1024); "; /// 実行(できない...) $mysqli->query( $sql ); print_r( $mysqli->error ); |
▼このコードを実行したら、次みたいに怒られた、、、
1 |
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INSERT INTO players (name, score) VALUES ('hoge', 256), ('fuga', 1024)' at line 6 |
別にSQL自体は間違ってないけど、実行できません。
なぜなら query 関数は1つのクエリしか実行できないから
代わりに mysqli::multi_query 関数を使えばよかった
実は mysqli には multi_query っていう複数クエリ用の関数が用意されてます。
以下が公式リファレンスでの multi_query の解説
オブジェクト指向型
mysqli::multi_query ( string $query ) : bool手続き型
mysqli_multi_query ( mysqli $link , string $query ) : boolセミコロンで連結されたひとつまたは複数のクエリを実行します。
引用元 : https://www.php.net/manual/ja/mysqli.multi-query.php
この説明の「セミコロン( ; )で連結された」ってところが重要なポイント
それ以外は query を使うときと同じです。
実際の multi_query のコード例はこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/// 複数クエリ $sql = " CREATE TABLE IF NOT EXISTS players ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), score BIGINT ); INSERT INTO players (name, score) VALUES ('hoge', 256), ('fuga', 1024), ('piyo', 64); "; /// とりあえず実行 $mysqli->multi_query( $sql ); print_r( $mysqli->error ); |
こうすればSQL自体にエラーが無ければ実行できます。
ただしセミコロン( ; )でステートメントを区切るのを忘れずに
SELECTしたとき multi_queryで結果データを全取得するには
もし SELECT * FROM hoge; みたいに複数クエリを実行した場合・・・
結果の取得は mysqli::query と比べると、少し特殊な手順になります。
- まずは next_result でクエリごとにループ回す
- その中で store_result で結果セット取得
- あとは fetch_assoc とかでゴニョゴニョ...
- その次の結果を more_result で取得
- 以下 1 ~ 4 のループ
▲ ざっくり書くとこういう感じ
具体的なコード例を出すなら、こんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$mysqli->multi_query( $sql ); do { if( $result = $mysqli->store_result() ) { print_r( '====================<br>' ); while( $row = $result->fetch_assoc() ) { print_r( 'name : '.$row['name'].', score : '.$row['score'].'<br>' ); } $result->close(); print_r( '====================<br><br>' ); } $mysqli->more_results(); } while ( $mysqli->next_result() ); print_r( $mysqli->error ); |
まあ少し複雑だけど、慣れるしかないですね。
結果セットのループに
next_result 、
結果セットの取得には
store_result を使う
この2つが大事、PHPで複数クエリを実行するなら気を付けたいです。
ちなみに複数クエリで server has gone away エラーが出たら...
それで最後に大事なことを1つ
実はこの multi_query 関数、
あまりにもクエリが大きすぎると 次みたいなエラー が出ます。
1 |
Warning: mysqli_multi_query() : MySQL server has gone away in ... |
僕自身、このエラーが 1000 くらいクエリを実行したとき起こりました。
なのでもしこういうエラーが出たなら、次の対処法を試すのがグッド です。
- パケットサイズを必要なだけ拡張する
- MySQLのタイムアウト時間を長くする
- ini_setでタイムアウト設定をしておく
詳しくは次記事でまとめたので、気になる人はチェック
クエリサイズが 1MB を超えるなら、絶対この設定はしとかないとダメです。
ここまでのまとめ
以上、PHPの mysqli で複数クエリを実行する方法でした。
単体のクエリは query 関数、複数クエリは multi_query を使えばOK
ただそれだけの話しです。
でもクエリサイズが大規模なら、パケットサイズの拡張も忘れずに。