【问题标题】:? LIKE (column || '%')?喜欢(列 || '%')
【发布时间】:2014-11-18 08:12:36
【问题描述】:

我可以有这样的条件:

SELECT * FROM table WHERE ? LIKE (column || '%')

? 是一个字符串参数值。例如,当列等于/admin/products

时,这些参数值?应该返回true
/admin/products/1
/admin/products/new
/admin/products/1/edit

这可能吗?

更新:添加了测试用例。

基本上,where 子句会呈现如下:

1.  ? LIKE (column || '%')
2.  '/admin/products/1' like ('/admin/products' || %)
3.  '/admin/products/1' like ('/admin/products%')

但它总是对我返回 false。

这些查询工作正常:

column = '/admin/products' --returns true
column = '/admin/products/1' --returns false
column LIKE '/admin/prod%' --returns true

当我将参数? 放在LIKE 子句之前时,就会出现问题。不允许吗?
如果不是,是否有任何解决方法?

【问题讨论】:

  • AFAIK 表名和列名不能被参数替换。
  • 这听起来像是前端/实现问题,而不是数据库问题。
  • @Scotch 我们实际上是在我们的系统上实现一个用户角色。我们将基本页面的 URL 放在数据库中,并在管理站点的基本控制器中对其进行验证,这样我们就不会有任何冗余代码。
  • SQL中+是加数字的运算符,不是字符连接的(连接字符串的运算符是||
  • @a_horse_with_no_name 已注意,修复了有关 SQL 字符串连接符号的问题。

标签: mysql sql postgresql pattern-matching prefix


【解决方案1】:

查询:

SELECT * FROM table WHERE ? LIKE (col || '%');

可以重写为(Postgres 和 MySQL):

SELECT * FROM table WHERE col = left(?, length(col));

正如所评论的,第一种形式也应该可以工作。不过,这可能很棘手,因为 具有特殊含义的字符 对于列中的LIKE(至少是_%\ 必须进行转义。如果您希望它与 MySQL 和 Postgres 一起使用,您必须在这两种实现中观察特殊字符。所以第二种形式在原则上更不容易出错

性能

这些查询都不能使用col 上的索引,两者都不是sargable。该问题可以重新评估为找到给定搜索模式? 的所有可能前缀,可以像在 dba.SE 上的相关答案(针对 Postgres)中类似的方式进行优化:

【讨论】:

  • 非常感谢!它也适用于 MySQL。你为我节省了一天的工作时间。
  • 它仍然没有解释为什么最初的问题出现了,但它肯定能完成这项工作。
  • 第一种形式也应该可以工作。但是,这可能会很棘手,因为像`_%\`这样的特殊字符in the column必须被转义。所以第二种形式更不容易出错。
【解决方案2】:

更换

SELECT * FROM table WHERE ? LIKE (column || '%')

通过

SELECT * FROM table WHERE ? LIKE CONCAT(column, '%')

为我工作。

也许 ||用作逻辑或运算而不是串联。

【讨论】:

  • 谢谢!它也适用于postgre吗?我们的生产数据库实际上是在 postgre 上,我们的开发环境是在 MySQL 上。
  • @JohnIsaiahCarmona:我强烈建议在开发和生产中使用相同的 RDBMS,否则您将继续遇到“令人惊讶的”问题。还有一个concat() function in Postgres,但|| 是标准SQL 连接运算符。还有the name is not "postgre".
  • @ErwinBrandstetter 他们实际上在他们的文档中声明 所有其他名称都不正确,尤其是 Postgre,哈哈,对不起。我的同事也在使用 PostgreSQL,但我需要一个更好的 IDE 用于我的数据库(表上编辑和其他东西),而我在 PostgreSQL 中找不到(我正在使用 MySQL Workbench)。但我个人认为海豚和大象是一样的;)
  • @John PostgreSQL 从 9.1 开始也有一个 concat 函数,工作示例:sqlfiddle.com/#!15/07da7/1
【解决方案3】:

为我工作。

PREPARE withparam(text) AS SELECT $1 LIKE ('/admin/products' || '%');

EXECUTE withparam('/admin/products/1');

返回真。

您的测试用例似乎无法准确反映手头的实际问题。

【讨论】:

  • 对不起,这只是一个错字。 :p 已经修复了。感谢您指出这一点。
  • @JohnIsaiahCarmona 我仍然相信您的真正问题在其他地方,并且测试用例并不能真正反映您在做什么。 select '/admin/products/1' like ('/admin/products%') 可以为您返回 false 是没有意义的。
  • 我实际上通过调试检查了生成的SQL查询,它是'/admin/products/1' like (url || '%'),但它确实返回false。我认为问题在于like 条件的实施不允许其后的表名。但是在 MySQL 上运行查询会返回 true。感谢您的帮助!我真的很感激!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-23
  • 2018-05-27
  • 2022-08-03
  • 2022-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多