Oracle 中不区分大小写的搜索

发布于 2024-10-24 19:26:37 字数 84 浏览 2 评论 0原文

LIKE 和其他比较运算符 = 等的默认行为区分大小写。

是否可以使它们不区分大小写?

The default behaviour of LIKE and the other comparison operators, = etc is case-sensitive.

Is it possible make them case-insensitive?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

穿透光 2024-10-31 19:26:38

也许你可以尝试使用

SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'

maybe you can try using

SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'
无声静候 2024-10-31 19:26:38

从 Oracle 12c R2 开始,您可以使用 整理运算符

COLLATE 运算符确定表达式的排序规则。此运算符使您能够覆盖数据库使用标准排序规则派生规则为表达式派生的排序规则。

COLLATE 运算符采用一个参数 collat​​ion_name,您可以为其指定命名排序规则或伪排序规则。如果排序规则名称包含空格,则必须将该名称用双引号引起来。

演示:

CREATE TABLE tab1(i INT PRIMARY KEY, name VARCHAR2(100));

INSERT INTO tab1(i, name) VALUES (1, 'John');
INSERT INTO tab1(i, name) VALUES (2, 'Joe');
INSERT INTO tab1(i, name) VALUES (3, 'Billy'); 
--========================================================================--
SELECT /*csv*/ *
FROM tab1
WHERE name = 'jOHN' ;
-- no rows selected

SELECT /*csv*/ *
FROM tab1
WHERE name COLLATE BINARY_CI = 'jOHN' ;
/*
"I","NAME"
1,"John"
*/

SELECT /*csv*/ *
FROM tab1 
WHERE name LIKE 'j%';
-- no rows selected

SELECT /*csv*/ *
FROM tab1 
WHERE name COLLATE BINARY_CI LIKE 'j%';
/*
"I","NAME"
1,"John"
2,"Joe"
*/

db<>fiddle 演示

From Oracle 12c R2 you could use COLLATE operator:

The COLLATE operator determines the collation for an expression. This operator enables you to override the collation that the database would have derived for the expression using standard collation derivation rules.

The COLLATE operator takes one argument, collation_name, for which you can specify a named collation or pseudo-collation. If the collation name contains a space, then you must enclose the name in double quotation marks.

Demo:

CREATE TABLE tab1(i INT PRIMARY KEY, name VARCHAR2(100));

INSERT INTO tab1(i, name) VALUES (1, 'John');
INSERT INTO tab1(i, name) VALUES (2, 'Joe');
INSERT INTO tab1(i, name) VALUES (3, 'Billy'); 
--========================================================================--
SELECT /*csv*/ *
FROM tab1
WHERE name = 'jOHN' ;
-- no rows selected

SELECT /*csv*/ *
FROM tab1
WHERE name COLLATE BINARY_CI = 'jOHN' ;
/*
"I","NAME"
1,"John"
*/

SELECT /*csv*/ *
FROM tab1 
WHERE name LIKE 'j%';
-- no rows selected

SELECT /*csv*/ *
FROM tab1 
WHERE name COLLATE BINARY_CI LIKE 'j%';
/*
"I","NAME"
1,"John"
2,"Joe"
*/

db<>fiddle demo

和影子一齐双人舞 2024-10-31 19:26:38

如果将 COLLATE 运算符放在表达式的末尾,它也可以工作,这对我来说似乎更干净。
所以你可以使用这个:

WHERE name LIKE 'j%' COLLATE BINARY_CI 

而不是这个:

WHERE name COLLATE BINARY_CI LIKE 'j%'

无论如何,我喜欢 COLLATE 运算符解决方案,原因如下:

  • 你只在表达式中放置一次,并且不需要担心多个 UPPER 或 LOWER 以及将它们放在哪里
  • 它与您需要的确切语句和表达式隔离,这与 ALTER SESSION 解决方案不同,ALTER SESSION 解决方案使其适用于所有内容。无论数据库或会话 NLS_SORT 设置如何,您的查询都将一致地工作。

The COLLATE operator also works if you put it at the end of the expression, and that seems cleaner to me.
So you can use this:

WHERE name LIKE 'j%' COLLATE BINARY_CI 

instead of this:

WHERE name COLLATE BINARY_CI LIKE 'j%'

Anyhow, I like the COLLATE operator solution for the following reasons:

  • you put it only once in the expression and you don't need to worry about multiple UPPER or LOWER, and where to put them
  • it is isolated to the exact statement and expression where you need it, unlike ALTER SESSION solution that makes it applicable to everything. And your query will work consistently regardless of the DB or session NLS_SORT setting.
£烟消云散 2024-10-31 19:26:38
select user_name
from my_table
where nlssort(user_name, 'NLS_SORT = Latin_CI') = nlssort('%AbC%', 'NLS_SORT = Latin_CI')
select user_name
from my_table
where nlssort(user_name, 'NLS_SORT = Latin_CI') = nlssort('%AbC%', 'NLS_SORT = Latin_CI')
世态炎凉 2024-10-31 19:26:38

你可以这样做:

where regexp_like(name, 'string
, 'i');

you can do something like that:

where regexp_like(name, 'string
, 'i');
青丝拂面 2024-10-31 19:26:37

在 Oracle 中,有 3 种主要方法可以在不使用全文索引的情况下执行不区分大小写的搜索。

最终选择哪种方法取决于您的个人情况;要记住的主要事情是,为了提高性能,您必须正确索引以进行不区分大小写的搜索。

1. 将列和字符串的大小写保持一致。

您可以使用 强制所有数据大小写相同UPPER()LOWER()

select * from my_table where upper(column_1) = upper('my_string');

或者

select * from my_table where lower(column_1) = lower('my_string');

如果 column_1 未在 upper(column_1)lower(column_1) 上建立索引,根据情况,这可能会强制进行全表扫描。为了避免这种情况,您可以创建一个 基于函数的索引

create index my_index on my_table ( lower(column_1) );

如果您使用 LIKE,则必须在要搜索的字符串周围连接一个 %

select * from my_table where lower(column_1) LIKE lower('my_string') || '%';

这个 SQL Fiddle 演示了所有这些查询中发生的情况。请注意解释计划,它指示何时使用索引以及何时不使用索引。

2.使用正则表达式。

从 Oracle 10g 开始 REGEXP_LIKE() 可用。您可以指定 _match_parameter_ 'i',以执行不区分大小写的搜索。

为了将其用作相等运算符,您必须指定字符串的开头和结尾,用克拉和美元符号表示。

select * from my_table where regexp_like(column_1, '^my_string

为了执行 LIKE 的等效功能,可以删除这些。

select * from my_table where regexp_like(column_1, 'my_string', 'i');

请小心这一点,因为您的字符串可能包含正则表达式引擎会以不同方式解释的字符。

此 SQL Fiddle 显示相同的示例输出,但使用 REGEXP_LIKE() 除外。

3. 在会话级别更改它。

NLS_SORT 参数控制排序的排序顺序以及各种比较运算符,包括 = 和 LIKE。您可以通过更改会话来指定二进制、不区分大小写的排序。这意味着在该会话中执行的每个查询都将执行不区分大小写的参数。

alter session set nls_sort=BINARY_CI

关于语言排序和字符串搜索有大量其他信息如果您想指定不同的语言,或者使用 BINARY_AI 进行不区分重音的搜索。

您还需要更改 NLS_COMP 参数;引用:

遵守 NLS_SORT 参数的确切运算符和查询子句
取决于 NLS_COMP 参数的值。如果操作员或
子句不遵循由 NLS_COMP 确定的 NLS_SORT 值,
使用的排序规则是 BINARY。

NLS_COMP的默认值为BINARY;但是,LINGUISTIC指定Oracle应该注意NLS_SORT的值:

WHERE 子句和 PL/SQL 中所有 SQL 操作的比较
块应使用 NLS_SORT 中指定的语言排序
范围。为了提高性能,您还可以定义一个
您想要其语言的列的语言索引
比较。

因此,您需要再次更改会话

alter session set nls_comp=LINGUISTIC

如文档中所述,您可能想要创建一个 语言索引以提高性能

create index my_linguistc_index on my_table 
   (NLSSORT(column_1, 'NLS_SORT = BINARY_CI'));
, 'i');

为了执行 LIKE 的等效功能,可以删除这些。

请小心这一点,因为您的字符串可能包含正则表达式引擎会以不同方式解释的字符。

此 SQL Fiddle 显示相同的示例输出,但使用 REGEXP_LIKE() 除外。

3. 在会话级别更改它。

NLS_SORT 参数控制排序的排序顺序以及各种比较运算符,包括 = 和 LIKE。您可以通过更改会话来指定二进制、不区分大小写的排序。这意味着在该会话中执行的每个查询都将执行不区分大小写的参数。

关于语言排序和字符串搜索有大量其他信息如果您想指定不同的语言,或者使用 BINARY_AI 进行不区分重音的搜索。

您还需要更改 NLS_COMP 参数;引用:

遵守 NLS_SORT 参数的确切运算符和查询子句
取决于 NLS_COMP 参数的值。如果操作员或
子句不遵循由 NLS_COMP 确定的 NLS_SORT 值,
使用的排序规则是 BINARY。

NLS_COMP的默认值为BINARY;但是,LINGUISTIC指定Oracle应该注意NLS_SORT的值:

WHERE 子句和 PL/SQL 中所有 SQL 操作的比较
块应使用 NLS_SORT 中指定的语言排序
范围。为了提高性能,您还可以定义一个
您想要其语言的列的语言索引
比较。

因此,您需要再次更改会话

如文档中所述,您可能想要创建一个 语言索引以提高性能

There are 3 main ways to perform a case-insensitive search in Oracle without using full-text indexes.

Ultimately what method you choose is dependent on your individual circumstances; the main thing to remember is that to improve performance you must index correctly for case-insensitive searching.

1. Case your column and your string identically.

You can force all your data to be the same case by using UPPER() or LOWER():

select * from my_table where upper(column_1) = upper('my_string');

or

select * from my_table where lower(column_1) = lower('my_string');

If column_1 is not indexed on upper(column_1) or lower(column_1), as appropriate, this may force a full table scan. In order to avoid this you can create a function-based index.

create index my_index on my_table ( lower(column_1) );

If you're using LIKE then you have to concatenate a % around the string you're searching for.

select * from my_table where lower(column_1) LIKE lower('my_string') || '%';

This SQL Fiddle demonstrates what happens in all these queries. Note the Explain Plans, which indicate when an index is being used and when it isn't.

2. Use regular expressions.

From Oracle 10g onwards REGEXP_LIKE() is available. You can specify the _match_parameter_ 'i', in order to perform case-insensitive searching.

In order to use this as an equality operator you must specify the start and end of the string, which is denoted by the carat and the dollar sign.

select * from my_table where regexp_like(column_1, '^my_string

In order to perform the equivalent of LIKE, these can be removed.

select * from my_table where regexp_like(column_1, 'my_string', 'i');

Be careful with this as your string may contain characters that will be interpreted differently by the regular expression engine.

This SQL Fiddle shows you the same example output except using REGEXP_LIKE().

3. Change it at the session level.

The NLS_SORT parameter governs the collation sequence for ordering and the various comparison operators, including = and LIKE. You can specify a binary, case-insensitive, sort by altering the session. This will mean that every query performed in that session will perform case-insensitive parameters.

alter session set nls_sort=BINARY_CI

There's plenty of additional information around linguistic sorting and string searching if you want to specify a different language, or do an accent-insensitive search using BINARY_AI.

You will also need to change the NLS_COMP parameter; to quote:

The exact operators and query clauses that obey the NLS_SORT parameter
depend on the value of the NLS_COMP parameter. If an operator or
clause does not obey the NLS_SORT value, as determined by NLS_COMP,
the collation used is BINARY.

The default value of NLS_COMP is BINARY; but, LINGUISTIC specifies that Oracle should pay attention to the value of NLS_SORT:

Comparisons for all SQL operations in the WHERE clause and in PL/SQL
blocks should use the linguistic sort specified in the NLS_SORT
parameter. To improve the performance, you can also define a
linguistic index on the column for which you want linguistic
comparisons.

So, once again, you need to alter the session

alter session set nls_comp=LINGUISTIC

As noted in the documentation you may want to create a linguistic index to improve performance

create index my_linguistc_index on my_table 
   (NLSSORT(column_1, 'NLS_SORT = BINARY_CI'));
, 'i');

In order to perform the equivalent of LIKE, these can be removed.

Be careful with this as your string may contain characters that will be interpreted differently by the regular expression engine.

This SQL Fiddle shows you the same example output except using REGEXP_LIKE().

3. Change it at the session level.

The NLS_SORT parameter governs the collation sequence for ordering and the various comparison operators, including = and LIKE. You can specify a binary, case-insensitive, sort by altering the session. This will mean that every query performed in that session will perform case-insensitive parameters.

There's plenty of additional information around linguistic sorting and string searching if you want to specify a different language, or do an accent-insensitive search using BINARY_AI.

You will also need to change the NLS_COMP parameter; to quote:

The exact operators and query clauses that obey the NLS_SORT parameter
depend on the value of the NLS_COMP parameter. If an operator or
clause does not obey the NLS_SORT value, as determined by NLS_COMP,
the collation used is BINARY.

The default value of NLS_COMP is BINARY; but, LINGUISTIC specifies that Oracle should pay attention to the value of NLS_SORT:

Comparisons for all SQL operations in the WHERE clause and in PL/SQL
blocks should use the linguistic sort specified in the NLS_SORT
parameter. To improve the performance, you can also define a
linguistic index on the column for which you want linguistic
comparisons.

So, once again, you need to alter the session

As noted in the documentation you may want to create a linguistic index to improve performance

尐籹人 2024-10-31 19:26:37

从 10gR2 开始,Oracle 允许通过设置 <代码>NLS_COMPNLS_SORT会话参数:

SQL> SET HEADING OFF
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY

NLS_COMP
BINARY


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         0

SQL>
SQL> ALTER SESSION SET NLS_COMP=LINGUISTIC;

Session altered.

SQL> ALTER SESSION SET NLS_SORT=BINARY_CI;

Session altered.

SQL>
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY_CI

NLS_COMP
LINGUISTIC


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         1

您还可以创建不区分大小写的索引:

create index
   nlsci1_gen_person
on
   MY_PERSON
   (NLSSORT
      (PERSON_LAST_NAME, 'NLS_SORT=BINARY_CI')
   )
;

此信息取自 Oracle 不区分大小写的搜索。文章提到了 REGEXP_LIKE 但它似乎也适用于旧的 =


在早于 10gR2 的版本中,这实际上是不可能完成的,如果您不需要不区分重音的搜索,通常的方法就是只UPPER()列和搜索表达式。

Since 10gR2, Oracle allows to fine-tune the behaviour of string comparisons by setting the NLS_COMP and NLS_SORT session parameters:

SQL> SET HEADING OFF
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY

NLS_COMP
BINARY


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         0

SQL>
SQL> ALTER SESSION SET NLS_COMP=LINGUISTIC;

Session altered.

SQL> ALTER SESSION SET NLS_SORT=BINARY_CI;

Session altered.

SQL>
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY_CI

NLS_COMP
LINGUISTIC


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         1

You can also create case insensitive indexes:

create index
   nlsci1_gen_person
on
   MY_PERSON
   (NLSSORT
      (PERSON_LAST_NAME, 'NLS_SORT=BINARY_CI')
   )
;

This information was taken from Oracle case insensitive searches. The article mentions REGEXP_LIKE but it seems to work with good old = as well.


In versions older than 10gR2 it can't really be done and the usual approach, if you don't need accent-insensitive search, is to just UPPER() both the column and the search expression.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文