MySQL: プリペアドステートメントのプレースホルダーの数は65535まで。
MySQLで大量にインサートするために、複数行を1つのINSERTで追加しようとしたら、次のエラーが発生してINSERTに失敗した。
SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders ....
プリペアドステートメントを使って、1つのクエリーで使用可能なプレースホルダーの上限は、65535
のようだ。
ネットには、同様の上限にひっかかってエラーが発生している事象の報告は多々見受けられた。しかし、エビデンスに基づいた情報が見つからなかったので頑張って調べてみた。
そうすると、stackoverflowでMySQLのソースを提示している情報を見つけた。実際にMySQLのソースを見てみると、それっぽい感じがする・・・
sql_prepare.cc
static bool init_param_array(Prepared_statement *stmt) { LEX *lex = stmt->lex; if ((stmt->param_count = lex->param_list.elements)) { if (stmt->param_count > (uint)UINT_MAX16) { /* Error code to be defined in 5.0 */ my_error(ER_PS_MANY_PARAM, MYF(0)); return true; }
https://github.com/mysql/mysql-server/blob/8.0/sql/sql_prepare.cc
ここで、比較に使用している UINT_MAX16
の定義がどういった内容なのか、不明なのでこちらの定義も、同じgithubのリポジトリ内のソースを検索してみる。
そうすると、下記の定義が見つかった。
include/my_inttypes.h #define UINT_MAX24 0x00FFFFFF #define INT_MIN16 (~0x7FFF) #define INT_MAX16 0x7FFF #define UINT_MAX16 0xFFFF #define INT_MIN8 (~0x7F)
0xFFFF
は 65535
である。
これで今後は自信を持って、プレースホルダーを使う事ができる。
しかし、65535個もプレースホルダーを同時に使う機会はそうそうないような気もする・・・・
ちなみに、エラーメッセージの定義を確認してみた。
エラーメッセージは、sql_prepare.cc の my_error(ER_PS_MANY_PARAM, MYF(0));
で行っているが、ここで指定されている定数?に対応するエラーメッセージは、messages_to_clients.txt
で定義されていた。
ER_PS_MANY_PARAM eng "Prepared statement contains too many placeholders" ger "Vorbereitete Anweisung enthält zu viele Platzhalter"
https://github.com/mysql/mysql-server/blob/8.0/share/messages_to_clients.txt
それにしても、公式のドキュメントにすら情報がないのはしんどい。