在H2中执行不区分大小写的字符串搜索?

时间:2018-04-19 11:52:16

标签: sql h2 case-sensitive

我正在使用H2运行一些最初设计用于MySQL的数据库代码,并且有一些查询需要以不区分大小写的方式匹配数据。我在JDBC连接URL中找到了“IGNORECASE = TRUE”选项,这在某些情况下有所帮助,但它似乎无处不在。例如,在MySQL中,我有以下(简化)查询:

select e.id from entities e left join ranges r on e.range=r.id
 where locate (?, e.name) between r.start and r.end

不幸的是,这在H2中不起作用,因为它以区分大小写的方式执行匹配,我需要它不敏感。

H2是否有一些选项可以改变像locate这样的函数的行为区分大小写?或者另一个能完成同样工作的功能?使用输入参数运行locate (?, lcase(e.name))是否也适用于小写,或者是否效率低或者在不明原因的情况下失败?

编辑 @AndrewMortan在评论中建议了一个问题的链接,其中包含相关问题的答案。我已经尝试了两个建议(在创建表之前使用SET COLLATION命令来设置默认排序规则并在需要进行不区分大小写的比较的字段中使用'VARCHAR_IGNORECASE'数据类型,不幸的是,两者都没有用过:

create schema test;
set schema test;
set collation en strength primary;
create table test ( t varchar_ignorecase(255) not null );
insert into test(t) values ('THIS SHOULD BE FINDABLE WITH A LOWER CASE SEARCH STRING');
select t, locate('should', t) from test;

产生结果:

T                                    LOCATE('should', T)  
THIS SHOULD BE FINDABLE WITH A ...   0

,而:

select t, locate('SHOULD', t) from test;

给出:

T                                    LOCATE('SHOULD', T)  
THIS SHOULD BE FINDABLE WITH A ...   6

1 个答案:

答案 0 :(得分:1)

为什么不尝试添加lower()功能?

select e.id from entities e left join ranges r on e.range=r.id
  where locate (lower(?), lower(e.name)) between r.start and r.end

这应该有用,还是我错了?

如果您经常在许多行上运行此查询,则可以创建虚拟列,如下所示:

alter table element add (
  name_lower varchar(100) as lower(name)
);

所以你的查询会更快:

select e.id from entities e left join ranges r on e.range=r.id
  where locate (lower(?), e.name_lower) between r.start and r.end

到底是什么,你甚至可以通过虚拟列进行索引:

create index ix_element_add_low on element (address_lower);

如果您认为它可以加快速度。