sqlstring中文文档|sqlstring js中文教程|解析
sqlstring
MySQL 的简单 SQL 转义和格式
安装
$ npm install sqlstring
用法
var SqlString = ;
转义查询值
注意这些转义值的方法仅在NO_BACKSLASH_ESCAPES
SQL 模式被禁用(这是 MySQL 服务器的默认状态)时才有效
。
为了避免 SQL 注入攻击,在 SQL 查询中使用任何用户提供的数据之前,您应该始终对其进行转义。您可以使用以下SqlString.escape()
方法执行此操作
:
var userId = 'some user provided value';var sql = 'SELECT * FROM users WHERE id = ' + SqlString;console; // SELECT * FROM users WHERE id = 'some user provided value'
或者,您可以使用?
字符作为您想要转义的值的占位符,如下所示:
var userId = 1;var sql = SqlString;console; // SELECT * FROM users WHERE id = 1
多个占位符以与传递相同的顺序映射到值。例如,在下面的查询foo
equals a
、bar
equals b
、baz
equalsc
和
id
will be 中userId
:
var userId = 1;var sql = SqlString;console; // UPDATE users SET foo = 'a', bar = 'b', baz = 'c' WHERE id = 1
这看起来类似于 MySQL 中的准备语句,但它实际上只是在SqlString.escape()
内部使用相同的方法。
注意这也不同于准备好的语句,因为所有语句都?
被替换,即使是包含在注释和字符串中的语句。
不同的值类型的转义方式不同,方法如下:
- 数字保持不变
- 布尔值转换为
true
/false
- 日期对象转换为
'YYYY-mm-dd HH:ii:ss'
字符串 - 缓冲区被转换为十六进制字符串,例如
X'0fa5'
- 字符串被安全转义
- 数组变成列表,例如
['a', 'b']
变成'a', 'b'
- 嵌套数组变成分组列表(用于批量插入),例如
[['a', 'b'], ['c', 'd']]
变成('a', 'b'), ('c', 'd')
- 具有
toSqlString
方法的对象将.toSqlString()
被调用并且返回值被用作原始 SQL。 - 对于对象上
key = 'val'
的每个可枚举属性,对象都会变成对。如果属性的值是函数,则跳过;如果属性的值是一个对象,则对其调用 toString() 并使用返回值。 undefined
/null
转换为NULL
NaN
/Infinity
保持原样。MySQL 不支持这些,并且尝试将它们作为值插入将触发 MySQL 错误,直到它们实现支持。
你可能已经注意到,这种转义允许你做这样的事情:
var post = id: 1 title: 'Hello MySQL';var sql = SqlString;console; // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
该toSqlString
方法允许您使用函数形成复杂的查询:
var CURRENT_TIMESTAMP = { return 'CURRENT_TIMESTAMP()'; } ;var sql = SqlString;console; // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42
要使用toSqlString
方法生成对象,SqlString.raw()
可以使用该方法。这将创建一个在?
占位符中使用时不会被触及的对象,对于将函数用作动态值非常有用:
注意提供给的字符串SqlString.raw()
在使用时将跳过所有转义函数,因此在传入未经验证的输入时要小心。
var CURRENT_TIMESTAMP = SqlString;var sql = SqlString;console; // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42
如果你觉得需要自己转义查询,也可以直接使用转义函数:
var sql = 'SELECT * FROM posts WHERE title=' + SqlString;console; // SELECT * FROM posts WHERE title='Hello MySQL'
转义查询标识符
如果你不能信任一个 SQL 标识符(数据库/表/列名),因为它是由用户提供的,你应该SqlString.escapeId(identifier)
像这样转义它:
var sorter = 'date';var sql = 'SELECT * FROM posts ORDER BY ' + SqlString;console; // SELECT * FROM posts ORDER BY `date`
它还支持添加限定标识符。它将逃脱这两个部分。
var sorter = 'date';var sql = 'SELECT * FROM posts ORDER BY ' + SqlString;console; // SELECT * FROM posts ORDER BY `posts`.`date`
如果您不想将其.
视为限定标识符,则可以将第二个参数设置为true
,以便将字符串保留为文字标识符:
var sorter = 'date.2';var sql = 'SELECT * FROM posts ORDER BY ' + SqlString;console; // SELECT * FROM posts ORDER BY `date.2`
或者,您可以使用??
字符作为您想要转义的标识符的占位符,如下所示:
var userId = 1;var columns = 'username' 'email';var sql = SqlString;console; // SELECT `username`, `email` FROM `users` WHERE id = 1
请注意,最后一个字符序列是实验性的,语法可能会改变
当您将 Object 传递给.escape()
or 时.format()
,.escapeId()
用于避免对象键中的 SQL 注入。
格式化查询
您可以使用SqlString.format
适当的 id 和值转义来准备具有多个插入点的查询。一个简单的例子如下:
var userId = 1;var inserts = 'users' 'id' userId;var sql = SqlString;console; // SELECT * FROM `users` WHERE `id` = 1
在此之后,您将拥有一个有效的转义查询,然后您可以安全地将其发送到数据库。如果您希望在实际将查询发送到数据库之前准备查询,这将非常有用。您还可以选择(但不是必需的)传入stringifyObject
and timeZone
,允许您提供将对象转换为字符串的自定义方法,以及特定于位置/时区感知的Date
。
这可以进一步与SqlString.raw()
助手结合以生成包含 MySQL 函数作为动态值的 SQL:
var userId = 1;var data = email: 'foobar@example.com' modified: SqlString ;var sql = SqlString;console; // UPDATE `users` SET `email` = 'foobar@example.com', `modified` = NOW() WHERE `id` = 1