【问题标题】:How to escape `$like` wildcard characters `%` and `_` in sequelize?如何在续集中转义`$like`通配符`%`和`_`?
【发布时间】:2023-04-06 19:21:01
【问题描述】:

如何告诉 sequelize(使用 sqlite3)在 $like 子句中转义通配符(%,_)?

例如,我想生成一个类似于下面的查询,它在任何“things.description”中找到文字字符串_cool_(不仅仅是被任何字符包围的单词“cool”):

SELECT * FROM things WHERE description LIKE '\_cool\_' ESCAPE '\';  

我猜它看起来像这样,但结果查询不是我希望的:

Thing.findAll({
  where: {
    description: {
      $like: ['?', '_cool_'],
      // ... or ...
      $like: '\\_cool\\_',
      $escape: '\\',
    }
  }
});

// => Executing (default):
// SELECT `id`, `description`
//   FROM `Things` AS `Thing`
//   WHERE `Thing`.`description` LIKE '?','_cool_';

很遗憾,我无法进入原始查询,因为“LIKE”子句将成为更大动态查询的一部分。

有什么想法吗?

【问题讨论】:

  • 如果您要转义一个单数反斜杠,那会不会是 \_cool\_
  • @Xorifelse 在 JavaScript 中,字符串文字 '\\_' 等于字符串 "\_"
  • 看来这可能只是sequelize目前的不足github.com/sequelize/sequelize/issues/4317

标签: javascript sqlite sequelize.js


【解决方案1】:

我唯一想到的就是类似

description: {
    $like: sequelize.literal(`'\\_cool\\_' ESCAPE '\\'`)
}

生成类似 SQL 的语句

LIKE '\_cool\_' ESCAPE '\'

【讨论】:

  • 好主意,只需要小心转义目标值本身以避免SQL注入。
  • Sequelize 提供escape 方法,可用于转义值以避免注入
【解决方案2】:

一个基于@piotrbienias 的完整解决方案,它接受任何用户输入并正确转义它 -

if (typeof query.string !== 'string') {
    throw Error('expecting string')
}
const inputRaw = query.string.replace(/(_|%|\\)/g, '\\$1');
const inputSec = sequelize.escape(`%${inputRaw}%`);
description = {
    $like: sequelize.literal(`${inputSec} ESCAPE '\\'`)
};

对于示例字符串 _cool_,这将转换为 -

LIKE '%\\_cool\\_%' ESCAPE '\\'

您可以根据实际用例更改逻辑以添加其他通配符

如果您使用 mysql 而不是 sqlite,则默认转义无论如何都是 \,因此可以删除 ESCAPE 声明

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    • 2021-12-22
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多