MySQL插入执行报ER_PARSE_ERROR语法错误,实际执行SQL与发送的不一致
问题原因
- 核心原因是直接拼接含用户输入的SQL字符串:当用户输入内容(也就是代码中的
intItem[j])包含单引号时,会破坏原有SQL的字符串闭合结构,导致语法错误。比如输入内容为what'test11时,拼接后会生成'what'test11'',中间的单引号会被MySQL识别为字符串结束标记,后续内容直接触发语法报错。 - 次要原因是异步循环的作用域问题:你使用
var声明循环变量j,var属于函数级作用域,当异步的connection.query回调执行时,循环已经执行完毕,j的值为循环最终值,导致实际执行的SQL和你循环中同步打印的当前批次SQL不一致。 - 额外问题:直接拼接SQL还存在严重的SQL注入风险,攻击者可以构造特殊输入篡改你的查询逻辑。
解决方案
直接使用MySQL驱动自带的**参数化查询(预编译)**能力,不要手动拼接SQL字符串,驱动会自动转义所有参数中的特殊字符,同时规避SQL注入风险,另外把循环变量改为let解决异步作用域问题,修改后代码如下:
// 把var改为let,避免异步回调作用域问题 for (let j = 0; j <= intLength - 1; j++) { console.log(intItem[j], "intents loop"); // 用?作为占位符,不直接拼接参数 const query1 = "INSERT INTO intents (intent, version_id, status_intent) VALUES (?, (SELECT MAX(versions.version_id) from versions), ?)"; // 参数按顺序放到数组里,传给query方法 const params = [intItem[j], enableStatus]; console.log(query1, params, "query11"); connection.query( query1, params, function (err, results) { if (err) { console.log(err, "error from new project in insert to intents"); } } ); }
参数化查询会自动把参数中的单引号转义为安全的转义格式,不会破坏SQL结构,同时驱动会严格把参数作为值处理,不会被识别为SQL指令,从根源解决语法错误和注入问题。
内容的提问来源于stack exchange,提问作者Sameer
相关产品推荐
相关产品推荐

