Поведінка за замовчуванням LIKE
та інших операторів порівняння =
тощо залежить від регістру.
Чи можна зробити їх нечутливими до регістру?
REGEXP_LIKE(username,'me','i')
замість LIKE?
Поведінка за замовчуванням LIKE
та інших операторів порівняння =
тощо залежить від регістру.
Чи можна зробити їх нечутливими до регістру?
REGEXP_LIKE(username,'me','i')
замість LIKE?
Відповіді:
Починаючи з 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, вам доведеться об'єднати a %
навколо себе рядок, який ви шукаєте.
select * from my_table where lower(column_1) LIKE lower('my_string') || '%';
Цей скрипт SQL демонструє, що відбувається у всіх цих запитах. Зверніть увагу на Плани пояснення, які вказують, коли використовується індекс, а коли - ні.
Від Oracle 10г і далі 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 показує той самий приклад виводу, за винятком використання 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 та інші, будь ласка, діліться.
`
є символом втечі @bozzmob. Не повинно бути різниць у виведенні, якщо рядок, над якою працює регулярний вираз, містить $
, це може спричинити проблеми лише в тому випадку, якщо вам потрібен $
літерал у регулярному виразі. Якщо у вас є конкретна проблема, я б задав інше питання, якщо цей коментар / відповідь не допомогла.
можливо, ви можете спробувати використовувати
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
є НЕ означає бути підстановочних, вірно? Вони свого роду плутають.