Поведение по умолчанию LIKE
и других операторов сравнения и =
т. Д. Чувствительно к регистру.
Можно ли сделать их без учета регистра?
REGEXP_LIKE(username,'me','i')
вместо как, как?
Поведение по умолчанию LIKE
и других операторов сравнения и =
т. Д. Чувствительно к регистру.
Можно ли сделать их без учета регистра?
REGEXP_LIKE(username,'me','i')
вместо как, как?
Ответы:
Начиная с 10gR2, Oracle позволяет тонко настраивать поведение сравнения строк, устанавливая параметры NLS_COMP
и NLS_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()
в столбце и поисковом выражении.
LIKE
выражения (например, WHERE foo LIKE '%abc%'
) уже достаточно медленные, если их нельзя проиндексировать, я не думаю, что это определенно связано с чувствительностью к регистру.
DBD::Oracle
, вы можете написать $ENV{NLS_SORT} = 'BINARY_CI'; $ENV{NLS_COMP} = 'LINGUISTIC';
перед вызовом `DBI-> connect`.
ALTER SESSION
только изменяет ваш локальный экземпляр исправления и означает ли это, как ваш текущий сеанс, то есть, если я закрою и снова открою, он будет сброшен. Есть ли способ, которым я могу видеть текущие значения, чтобы, если он сохранялся везде, я мог вернуться к исходным настройкам ...
Существует 3 основных способа выполнения поиска без учета регистра в Oracle без использования полнотекстовых индексов.
В конечном итоге, какой метод вы выберете, зависит от ваших индивидуальных обстоятельств; Главное, что нужно помнить, это то, что для повышения производительности вы должны правильно индексировать для поиска без учета регистра.
Вы можете заставить все ваши данные быть в одном и том же случае с помощью 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 демонстрирует, что происходит во всех этих запросах. Обратите внимание на планы объяснения, которые указывают, когда индекс используется, а когда нет.
От Oracle 10g и REGEXP_LIKE()
более доступна. Вы можете указать _match_parameter_ 'i'
, чтобы выполнить поиск без учета регистра.
Чтобы использовать это как оператор равенства, вы должны указать начало и конец строки, которая обозначается в каратах и знаком доллара.
select * from my_table where regexp_like(column_1, '^my_string$', 'i');
Чтобы выполнить эквивалент LIKE, их можно удалить.
select * from my_table where regexp_like(column_1, 'my_string', 'i');
Будьте осторожны с этим, поскольку ваша строка может содержать символы, которые будут по-разному интерпретироваться механизмом регулярных выражений.
Эта SQL Fiddle показывает тот же пример вывода, за исключением использования REGEXP_LIKE ().
Параметр NLS_SORT управляет последовательностью сортировки для упорядочения и различных операторов сравнения, в том числе =
и LIKE. Вы можете указать двоичную сортировку без учета регистра, изменив сеанс. Это будет означать, что каждый запрос, выполненный в этом сеансе, будет выполнять параметры без учета регистра.
alter session set nls_sort=BINARY_CI
Существует много дополнительной информации о лингвистической сортировке и поиске строк, если вы хотите указать другой язык или выполнить нечувствительный к акценту поиск с помощью BINARY_AI.
Вам также необходимо изменить параметр NLS_COMP ; Цитировать:
Точные операторы и предложения запроса, которые подчиняются параметру NLS_SORT, зависят от значения параметра NLS_COMP. Если оператор или предложение не подчиняются значению NLS_SORT, как определено NLS_COMP, используемое сопоставление - BINARY.
Значением по умолчанию NLS_COMP является BINARY; но LINGUISTIC указывает, что Oracle должен обратить внимание на значение NLS_SORT:
Для сравнения всех операций SQL в предложении WHERE и в блоках PL / SQL следует использовать лингвистическую сортировку, указанную в параметре NLS_SORT. Чтобы повысить производительность, вы также можете определить лингвистический индекс для столбца, для которого вы хотите лингвистические сравнения.
Итак, еще раз, вам нужно изменить сеанс
alter session set nls_comp=LINGUISTIC
Как отмечено в документации, вы можете создать лингвистический индекс для повышения производительности.
create index my_linguistc_index on my_table
(NLSSORT(column_1, 'NLS_SORT = BINARY_CI'));
select * from my_table where lower(column_1) LIKE lower('my_string') || '%';
вместо select * from my_table where lower(column_1) LIKE lower('my_string%');
? Это дает какое-то преимущество?
regexp_like
, есть ли способ избежать таких строк? Например, если в строке есть $, результат будет не таким, как мы ожидаем. // cc @Ben и другие, пожалуйста, поделитесь.
`
это escape-символ @bozzmob. Не должно быть никакой разницы в выводе, если строка, над которой работает регулярное выражение, содержит a $
, это может вызвать проблемы только в том случае, если вам нужно $
литерал в регулярном выражении. Если у вас есть конкретная проблема, я бы задал другой вопрос, если этот комментарий / ответ не помог.
может быть, вы можете попробовать использовать
SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'
WHERE upper(user_name) LIKE UPPER('%ME%')
тогда? :)
UPPER
параметр ввода тоже?
upper
функции вы теряете индекс, у вас есть идеи, как сделать поиск с помощью индекса?
Из Oracle 12c R2 вы можете использовать COLLATE operator
:
Оператор COLLATE определяет параметры сортировки для выражения. Этот оператор позволяет вам переопределить параметры сортировки, которые база данных получит для выражения, используя стандартные правила получения параметров сортировки.
Оператор COLLATE принимает один аргумент, collation_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"
*/
select user_name
from my_table
where nlssort(user_name, 'NLS_SORT = Latin_CI') = nlssort('%AbC%', 'NLS_SORT = Latin_CI')
%
«s в первом аргументе вашего второй NLSSORT
являются не значит быть подстановочными, верно? Они отчасти смущают.