如何在批量插入中使用 mysql / Node.js 中的 sql 字符串正确转义?
How to properaly escape using mysql / sqlstring in Node.js in bulk INSERT?
我正在使用这些节点模块:
const mysql = require('mysql');
const SqlString = require('sqlstring');
我从文件中读取 JSON 并将 JSON 解析为嵌套数组。然后我将嵌套数组传递到一个批量 MySQL INSERT.
这适用于 26 个文件中的 25 个文件并加载超过 500 条记录。一个文件有 21 JSON 条记录,只有以下记录失败:
[
{
"abstract": "... AWS Shared responsibility model: https://aws.amazon.com/compliance/shared-responsibility-model/; Enabling object-level logs in S3: ...",
"title": "Defeating a Cloud Breach Part 1"
}
]
我已将问题隔离到 "abstract" 字段。
我尝试在使用 "mysql" 和 connection.escape() 和 SqlString.escape() 加载到数组之前转义 "abstract" 的值=55=] 模块,分别。这两种情况都无法纠正导致 INSERT 失败的任何原因。
无论使用何种方法,INSERT 都会返回 "undefined" 失败。成功的 INSERT returns 类似于:
OkPacket {
fieldCount: 0,
affectedRows: 4,
insertId: 142,
serverStatus: 2,
warningCount: 0,
message: '&Records: 4 Duplicates: 0 Warnings: 0',
protocol41: true,
changedRows: 0
}
MySQLtable中的"abstract"列属于"text"类型,还有许多其他记录的长度超过了上述问题记录。
SqlString——当我遍历 JSON 键/值时,我尝试在放入嵌套数组之前转义字符串。
示例:摘要 = SqlString.escape(值))
我还尝试了整个 INSERT 语句,因此:
var sql = "INSERT INTO tbl (abstract,title,url,key_word) VALUES ?";
sql = SqlString.format(sql, [dbVals]);
var query = client.query(sql, function(err, result) {
console.log(result);
});
显然在上面的 clode 中 "client" 是 "mysql" CONNECTIONS 的一个实例(这就是为什么我也尝试起诉 mysql.escape() 和 client.escape( ) 代替 SqlString.escape())
但我得到的结果完全相同 只有这一条记录。
我已确认此内容是问题所在,因为我已删除上面的记录并将抽象的值设置为空字符串,并且在这两个实例中批量插入都成功。
我希望能有第二双眼睛。更好的是,我希望能得到指导,指出我在正确转义内容方面做错了什么,这样以后就不会再担心了。
谢谢。
编辑:向问题添加了更多详细信息。
我怀疑您的问题可能与架构有关。同样令人困惑:您的示例的一部分表明您正在尝试插入 4 个值 (abstract,title,url,key_word)
,但您的有效负载仅包含 2 个字段 - 不清楚该差异或如何在数据库端处理 defaults/nulls。
使用最佳猜测模式使用您提供的示例负载进行测试,我没有遇到任何问题。由于您的有效负载仅包含 2 个字段,因此我的测试仅包含这些字段。以下每个组件的示例可与您自己的组件进行比较。
如果您仍然遇到问题,请随时分享有关您的数据库、table 架构和字段的更多详细信息。您的数据库的 charset
、table 和字段可能也是一个很好的调查细节。
数据库详细信息
MySQL v5.7.12
CREATE TABLE `tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`abstract` text,
`title` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
节点
//
// other require items here as well depending on file location in project
//
const mysql = require('mysql');
const db = mysql.createPool({
connectionLimit: 10,
host: process.env.DB_HOST || '127.0.0.1',
user: process.env.DB_USER || 'local_user',
password: process.env.DB_PASSWORD || 'local_password',
database: process.env.DB_NAME || 'local_database',
multipleStatements: true,
charset: 'utf8mb4' // necessary if you might need support for emoji characters
});
let entries = [
{
"abstract": "An easy one",
"title": "Defeating a Cloud Breach Part 0"
},
{
"abstract": "... AWS Shared responsibility model: https://aws.amazon.com/compliance/shared-responsibility-model/; Enabling object-level logs in S3: ...",
"title": "Defeating a Cloud Breach Part 1"
},
{
"abstract": "Another easy one",
"title": "Defeating a Cloud Breach Part 2"
}
]
let keys = Object.keys(entries[0]);
let values = entries.map( obj => keys.map( key => obj[key]));
let sql = 'INSERT INTO tbl (' + keys.join(',') + ') VALUES ?;';
db.query(sql, [values], function (error, results) {
if (error) console.log(error.code);
console.log(results);
});
结果
OkPacket {
fieldCount: 0,
affectedRows: 3,
insertId: 1,
serverStatus: 2,
warningCount: 0,
message: '&Records: 3 Duplicates: 0 Warnings: 0',
protocol41: true,
changedRows: 0
}
我正在使用这些节点模块:
const mysql = require('mysql');
const SqlString = require('sqlstring');
我从文件中读取 JSON 并将 JSON 解析为嵌套数组。然后我将嵌套数组传递到一个批量 MySQL INSERT.
这适用于 26 个文件中的 25 个文件并加载超过 500 条记录。一个文件有 21 JSON 条记录,只有以下记录失败:
[
{
"abstract": "... AWS Shared responsibility model: https://aws.amazon.com/compliance/shared-responsibility-model/; Enabling object-level logs in S3: ...",
"title": "Defeating a Cloud Breach Part 1"
}
]
我已将问题隔离到 "abstract" 字段。
我尝试在使用 "mysql" 和 connection.escape() 和 SqlString.escape() 加载到数组之前转义 "abstract" 的值=55=] 模块,分别。这两种情况都无法纠正导致 INSERT 失败的任何原因。
无论使用何种方法,INSERT 都会返回 "undefined" 失败。成功的 INSERT returns 类似于:
OkPacket {
fieldCount: 0,
affectedRows: 4,
insertId: 142,
serverStatus: 2,
warningCount: 0,
message: '&Records: 4 Duplicates: 0 Warnings: 0',
protocol41: true,
changedRows: 0
}
MySQLtable中的"abstract"列属于"text"类型,还有许多其他记录的长度超过了上述问题记录。
SqlString——当我遍历 JSON 键/值时,我尝试在放入嵌套数组之前转义字符串。
示例:摘要 = SqlString.escape(值))
我还尝试了整个 INSERT 语句,因此:
var sql = "INSERT INTO tbl (abstract,title,url,key_word) VALUES ?";
sql = SqlString.format(sql, [dbVals]);
var query = client.query(sql, function(err, result) {
console.log(result);
});
显然在上面的 clode 中 "client" 是 "mysql" CONNECTIONS 的一个实例(这就是为什么我也尝试起诉 mysql.escape() 和 client.escape( ) 代替 SqlString.escape())
但我得到的结果完全相同 只有这一条记录。
我已确认此内容是问题所在,因为我已删除上面的记录并将抽象的值设置为空字符串,并且在这两个实例中批量插入都成功。
我希望能有第二双眼睛。更好的是,我希望能得到指导,指出我在正确转义内容方面做错了什么,这样以后就不会再担心了。
谢谢。
编辑:向问题添加了更多详细信息。
我怀疑您的问题可能与架构有关。同样令人困惑:您的示例的一部分表明您正在尝试插入 4 个值 (abstract,title,url,key_word)
,但您的有效负载仅包含 2 个字段 - 不清楚该差异或如何在数据库端处理 defaults/nulls。
使用最佳猜测模式使用您提供的示例负载进行测试,我没有遇到任何问题。由于您的有效负载仅包含 2 个字段,因此我的测试仅包含这些字段。以下每个组件的示例可与您自己的组件进行比较。
如果您仍然遇到问题,请随时分享有关您的数据库、table 架构和字段的更多详细信息。您的数据库的 charset
、table 和字段可能也是一个很好的调查细节。
数据库详细信息
MySQL v5.7.12
CREATE TABLE `tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`abstract` text,
`title` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
节点
//
// other require items here as well depending on file location in project
//
const mysql = require('mysql');
const db = mysql.createPool({
connectionLimit: 10,
host: process.env.DB_HOST || '127.0.0.1',
user: process.env.DB_USER || 'local_user',
password: process.env.DB_PASSWORD || 'local_password',
database: process.env.DB_NAME || 'local_database',
multipleStatements: true,
charset: 'utf8mb4' // necessary if you might need support for emoji characters
});
let entries = [
{
"abstract": "An easy one",
"title": "Defeating a Cloud Breach Part 0"
},
{
"abstract": "... AWS Shared responsibility model: https://aws.amazon.com/compliance/shared-responsibility-model/; Enabling object-level logs in S3: ...",
"title": "Defeating a Cloud Breach Part 1"
},
{
"abstract": "Another easy one",
"title": "Defeating a Cloud Breach Part 2"
}
]
let keys = Object.keys(entries[0]);
let values = entries.map( obj => keys.map( key => obj[key]));
let sql = 'INSERT INTO tbl (' + keys.join(',') + ') VALUES ?;';
db.query(sql, [values], function (error, results) {
if (error) console.log(error.code);
console.log(results);
});
结果
OkPacket {
fieldCount: 0,
affectedRows: 3,
insertId: 1,
serverStatus: 2,
warningCount: 0,
message: '&Records: 3 Duplicates: 0 Warnings: 0',
protocol41: true,
changedRows: 0
}