如何在 Knex 中像查询一样逃避 %?
Posted
技术标签:
【中文标题】如何在 Knex 中像查询一样逃避 %?【英文标题】:How do I escape % in Knex where like query? 【发布时间】:2018-10-23 22:07:45 【问题描述】:我正在使用knex
来生成我的 SQL 查询。在knex
文档中,它显示了这一点
knex('users').where('columnName', 'like', '%rowlikeme%')
现在在我的应用程序中,我这样做了:
function search(term)
term = "%" + term + "%";
knex('table').where('description', 'like', term);
// ...
如何转义 %
以便它也搜索 %
作为术语的一部分?
谢谢。
【问题讨论】:
【参考方案1】:使用 RLIKE 代替 LIKE 如下,它应该适合你。
function search(term)
knex('table').where('description','rlike',term);
...
【讨论】:
嗨,rlike 没有通过测试用例。示例:搜索词是“40%”。结果应显示:“Microscopic 40% Bacterialium”、“40% Alcohol”、“Creatine 40%”,但未显示“Creatine 40%”和“Microscopic 40% Bacterialium”。 你能不能用“ ` ” as 尝试一次把词放在一起:knex('table').where('description','like',term
);
如果我在术语前后添加 %,它将回复所有 3 个三个结果。如果我不这样做,它在使用 like 关键字时不会返回任何内容。
因为,这是喜欢的规则。例如,如果您有一个像“World”这样的值并使用 like 搜索“%orl%”,那么它将返回。但如果您搜索“orl”,则不会。这里 '%' 表示一个或多个字符【参考方案2】:
我有一段时间没有使用 knex,所以我无法测试这个。但是你有没有试图从字面上逃避 %?我希望这是你想要的。
let term = "%something%"
let parsedTerm = term.replace("%", "\%")
console.log(parsedTerm);
请告诉我。
【讨论】:
【参考方案3】:对于这种情况,我使用
来自es6
(安全版本)的字符串插值
knex('table').where('description', 'like', `%$term%`)
或??
参数binding
knex('table').whereRaw('description like \'%??%\'', [term])
但在第一种情况下,您必须 100% 确定该术语是有效的,因为 possibility of SQL injection。
【讨论】:
first例子有SQL注入的可能。第二种是使用命名参数,所以应该是安全的。 第一个对我不起作用。当 term 为 'foo' 时,绑定为 'undefinedfooundefined'。 @user128216 为什么第一个例子where('description', 'like',
%$term%)
容易发生sql注入?这不是和参数绑定一样安全吗?参考链接没有提到容易发生 sql 注入的地方,只是原始的。
.where
中的术语被转义,因此没有注入风险:github.com/knex/documentation/issues/73#issuecomment-572482153
第二个错误严重,根本不应该工作(??
绑定应该只用于标识符,所以如果term
中有点,它将失败)。第一个应该没问题,但我不知道它是否真的能够匹配%
char。【参考方案4】:
Knex 没有与 ESCAPE
关键字 [1] 等效的关键字,因此您必须执行这样的原始查询,它将搜索具有 name === "%foo%"
的用户:
knex.raw('select * from users where name like ? escape \', ['\%foo\%'])
而且,在搜索词的开头使用未转义的通配符,将搜索 name
以 "%foo%"
结尾的用户:
knex.raw('select * from users where name like ? escape \', ['%\%foo\%'])
[1] 关闭功能请求:https://github.com/knex/knex/issues/648
【讨论】:
通过阅读 SQL 文档,这种做法是有意义的并且可以工作。虽然knex('users').whereRaw('?? like ? escape \\%, ['name', '%\\%foo%'])
可能更接近工作解决方案。【参考方案5】:
你有没有试过这个
knex('Quotes').where('quoteBody', 'like', **'%'+Quote+'%'**)
只是常规的 javascript 转义就可以了。
【讨论】:
【参考方案6】:@coockoo 对这两个 SQL 的回答都不正确。他们的第一个仍然允许%
通过,因为Knex 不会为LIKE
操作逃脱%
。第二个 SQL 根本不起作用,因为 Knex 用引号包裹了绑定值。
正确的方法应该是
const term = '10%'
const b = knex('table').where('description', 'like', `%$term.replaceAll('%', '\\%')%`)
b.toString()
的输出为:
select * from "table" where "description" like E'%10\\%%'
Postgres 会将E'\\%'
解释为'\%'
,这是一个转义的百分号,根据:https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE 默认情况下,如果您使用的是较新的 Postgres 版本。
这可以用这张表来验证:
CREATE TABLE test (
description character varying(256)
);
INSERT INTO test VALUES ('a%b');
并测试以下内容:
-
不要像其他人建议的那样转义
%
。这不应该工作。
knex('test').where('description', 'like', 'a%%%b').toString()
select * from "test" where "description" like 'a%%%b'
description
-------------
a%b
(1 row)
在给 Knex 之前转义 %
。
-
这应该不返回任何行:
knex('test').where('description', 'like', 'a\\%\\%\\%b').toString()
select * from "test" where "description" like E'a\\%\\%\\%b'
description
-------------
(0 rows)
-
这应该返回
'a%b'
:
knex('test').where('description', 'like', 'a\\%b').toString()
select * from "test" where "description" like E'a\\%b'
description
-------------
a%b
(1 row)
SQL 小提琴:http://sqlfiddle.com/#!17/d2f5e/1
【讨论】:
【参考方案7】:所以我一直在寻找一种将 LOWER 函数应用于参数的正确方法。这是对我来说似乎工作正常的解决方案:
builder.whereRaw('LOWER(last_name) LIKE LOWER(?)', [`%$lastName%`])
【讨论】:
以上是关于如何在 Knex 中像查询一样逃避 %?的主要内容,如果未能解决你的问题,请参考以下文章