如何在不使用LIKE的情况下检查Oracle中字符串中的子字符串?假设我想从表中选择姓氏中包含字母“z”的所有用户:
SELECT * FROM users WHERE last_name LIKE "%z%";
这样可行,但我不想使用LIKE。还有其他一些我可以使用的功能吗?
答案 0 :(得分:14)
答案 1 :(得分:6)
如果您只对'z'感兴趣,可以创建一个基于函数的索引。
CREATE INDEX users_z_idx ON users (INSTR(last_name,'z'))
然后您的查询将使用WHERE INSTR(last_name,'z') > 0
。
使用这种方法,您必须为可能要搜索的每个字符创建单独的索引。我想如果你经常这样做,那么为每个字母创建一个索引可能是值得的。
另外,请记住,如果您的数据的名称以标准方式大写(例如,“Zaxxon”),那么您的示例和我的示例都不会与以Z开头的名称匹配。您可以通过以下方式对此进行更正在搜索表达式中包括LOWER:INSTR(LOWER(last_name),'z')
。
答案 2 :(得分:5)
您可以使用INSTR这样做:
SELECT * FROM users WHERE INSTR(LOWER(last_name), 'z') > 0;
如果子字符串不在字符串中,则INSTR返回零。
出于兴趣,你为什么不想使用?
编辑:我冒昧地使搜索案例不敏感,所以你不要错过Bob Zebidee。 : - )
答案 3 :(得分:2)
数据库针对常见使用场景进行了大量优化(LIKE就是其中之一)。
如果您希望保持在数据库级别,则无法找到更快捷的搜索方式。
答案 4 :(得分:0)
请记住,如果包含与谓词匹配的行的块数明显小于表中的块总数,则只需使用除全表扫描之外的任何内容来查找这些值。这就是为什么当你使用LIKE'%x%'时,Oracle通常会拒绝使用索引来进行全面扫描,其中x是一个非常小的字符串。例如,如果优化器认为使用索引仍然需要对(例如)20%的表块进行单块读取,那么全表扫描可能是比索引扫描更好的选择。
有时您知道您的谓词比优化程序可以估计的更具选择性。在这种情况下,您可以考虑提供优化器提示以在相关列上执行索引快速全扫描(特别是如果索引比表格小得多)。
SELECT /*+ index_ffs(users (users.last_name)) */
*
FROM users
WHERE last_name LIKE "%z%"