大小写敏感和不敏感在SQLite中的使用方法

61
在SQLite中,可以通过使用以下命令来更改“LIKE”操作符的区分大小写行为:

PRAGMA case_sensitive_like = true/false;

PRAGMA case_sensitive_like=ON;
PRAGMA case_sensitive_like=OFF;

然而在我的情况下,我希望执行一个查询,其中一部分是区分大小写的,另一部分不是。例如:

SELECT * FROM mytable
WHERE caseSensitiveField like 'test%'
AND caseInsensitiveField like 'g2%'

这是可能的吗?


https://dev59.com/uXNA5IYBdhLWcg3wZ9DU#973777 - CBroe
7个回答

49

您可以在不区分大小写的字段上使用UPPER关键字,然后将您的LIKE语句转换为大写。例如:

您可以在不区分大小写的字段上使用UPPER关键字,然后将您的LIKE语句转换为大写。例如:

SELECT * FROM mytable 
WHERE caseSensitiveField like 'test%' 
AND UPPER(caseInsensitiveField) like 'G2%'

1
@AlexanderMalakhov对于意大利和德国字符也适用。只需确保数据库和导入其中的数据都以UTF-8编码,就可以正常工作。 - Phantômaxx
23
注意,你不需要使用Upper函数,因为Like默认是不区分大小写的。 - Phantômaxx
6
可以做到,但需要进行调整。根据官方FAQ的说法:SQLite的默认配置只支持ASCII字符的不区分大小写比较。 - Alexander Malakhov
3
通过删除 "UPPER()",您最终得到与 OP 在问题中发布的相同代码。如果您想完全更改答案,请这样做;如果您想删除答案,请说明;但是您所做的编辑毫无意义。 - Matt
@Rotwang 你是怎么做到的?对我来说,select upper('ä') 在 utf8 数据库中返回 'ä';。官方常问问题(FAQ)上说 sqlite 并不区分大小写字母(除了 ASCII 字符)。 - Antony Hatchkins
显示剩余5条评论

8

在SQLite中,您可以使用GLOB而不是LIKE进行模式搜索。例如:

SELECT * FROM mytable
WHERE caseSensitiveField GLOB 'test*'
AND caseInsensitiveField LIKE 'g2%'

采用这种方法,您就不必担心PRAGMA了。


3
LIKE 'g2%' 默认情况下只对 ASCII 字符的不区分大小写进行匹配。 % 匹配的部分无所谓,因为它代表任何字符。但是,“g2”必须是非 Unicode 字符才能进行不区分大小写的匹配。'üb%'将匹配 über,但不会匹配 Über。请参阅 https://www.sqlite.org/faq.html#q18 - dre-hh

5

使用普通比较,它们默认情况下是区分大小写的(除非您已声明列COLLATE NOCASE):

SELECT *
FROM mytable 
WHERE caseSensitiveField >= 'test'
  AND caseSensitiveField <  'tesu'
  AND caseInsensitiveField LIKE 'g2%'

只有当原始的LIKE搜索前缀时,此方法才能生效,但可以使用索引。


3
我知道这是一个老问题,但如果你在使用Java编码并遇到了这个问题,这可能会有所帮助。您可以注册一个处理类似检查的函数。我从这篇文章中得到了贴士:https://dev59.com/h07Sa4cB1Zd3GeqP7uYF#29831950 解决方案依赖于sqlite jdbc:https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc 在我的情况下,我只需要查看某个字符串是否作为另一个字符串的一部分存在(如'%mystring%'),因此我创建了Contains函数,但应该可以扩展此功能以使用正则表达式或其他方式进行更多类似SQL的检查。
要在SQL中使用该函数来查看MyCol是否包含“searchstring”,您需要执行以下操作:
select * from mytable where Contains(MyCol, 'searchstring')

以下是我的Contains函数:

public class Contains extends Function {

    @Override
    protected void xFunc() throws SQLException {
        if (args() != 2) {
            throw new SQLException("Contains(t1,t2): Invalid argument count. Requires 2, but found " + args());
        }
        String testValue = value_text(0).toLowerCase();
        String isLike = value_text(1).toLowerCase();

        if (testValue.contains(isLike)) {
            result(1);
        } else {
            result(0);
        }
    }
}

要使用此功能,您必须先注册它。当您完成使用后,可以选择销毁它。以下是操作步骤:

public static void registerContainsFunc(Connection con) throws SQLException   {
    Function.create(con, Contains.class.getSimpleName(), new Contains());
}
public static void destroyContainsFunc(Connection con) throws SQLException {
    Function.destroy(con, Contains.class.getSimpleName());
}

发现代码中有一个 Bug。如果你在使用 Contains 函数的列允许空值,那么在应用 toLowerCase 函数之前,应该先检查 value_text(n) 是否为空。 - Jarle Jacobsen

0

正如其他人所提到的,SQLite也提供了GLOB函数,它是区分大小写的。

假设g2*是用户在应用程序级别输入的文本。为了简化应用程序端的语法并使GLOB不区分大小写,需要将文本规范化为一个共同的大小写:

SELECT * FROM mytable WHERE LOWER(caseInsensitiveField) GLOB LOWER('g2*');

如果需要使用UNICODE,请仔细测试LOWER和UPPER以确认它们按预期运行。GLOB是SQLite特定的扩展函数。构建支持多个数据库供应商的通用语法引擎是非常困难的。

0
SQLite有<exp> COLLATE <collate>,可以添加到任何表达式中,使其区分大小写或不区分大小写。
SELECT * FROM mytable 
WHERE caseSensitiveField like 'test%' 
AND caseInsensitiveField like 'G2%' COLLATE NOCASE

0

我使用了正则表达式来完成我需要的功能。我想要识别所有不是全小写的单词"In"的出现次数。

select [COL] from [TABLE] where [COL] REGEXP '\bIn\b';

例子:

with x as (select 'in' Diff_Ins union select 'In' Diff_Ins)
select Diff_Ins from x where Diff_Ins REGEXP '\bIn\b';

2
提醒其他读者,SQLite默认情况下没有REGEXP。 "REGEXP运算符是regexp()用户函数的特殊语法。默认情况下未定义regexp()用户函数,因此使用REGEXP运算符通常会导致错误消息。" https://www.sqlite.org/lang_expr.html#regexp - Captain Man

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接