Le comportement par défaut de LIKE
et des autres opérateurs de comparaison, =
etc. est sensible à la casse.
Est-il possible de les rendre insensibles à la casse?
REGEXP_LIKE(username,'me','i')
au lieu de LIKE?
Le comportement par défaut de LIKE
et des autres opérateurs de comparaison, =
etc. est sensible à la casse.
Est-il possible de les rendre insensibles à la casse?
REGEXP_LIKE(username,'me','i')
au lieu de LIKE?
Réponses:
Depuis 10gR2, Oracle permet d'affiner le comportement des comparaisons de chaînes en définissant les paramètres de session NLS_COMP
et 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
Vous pouvez également créer des index insensibles à la casse:
create index
nlsci1_gen_person
on
MY_PERSON
(NLSSORT
(PERSON_LAST_NAME, 'NLS_SORT=BINARY_CI')
)
;
Ces informations proviennent de recherches insensibles à la casse d' Oracle . L'article mentionne REGEXP_LIKE
mais il semble fonctionner aussi avec du bon vieux =
.
Dans les versions plus anciennes que 10gR2, cela ne peut pas vraiment être fait et l'approche habituelle, si vous n'avez pas besoin d'une recherche insensible aux accents, consiste à utiliser à la UPPER()
fois la colonne et l'expression de recherche.
LIKE
expressions arbitraires (par exemple WHERE foo LIKE '%abc%'
) sont déjà suffisamment lentes si elles ne peuvent pas être indexées, je ne pense pas que ce soit spécifiquement lié à la sensibilité à la casse.
DBD::Oracle
, vous pouvez écrire $ENV{NLS_SORT} = 'BINARY_CI'; $ENV{NLS_COMP} = 'LINGUISTIC';
avant d'appeler `DBI-> connect`.
ALTER SESSION
que modifier votre instance locale de la correction et cela signifie-t-il que votre session actuelle, c'est-à-dire que si je ferme et rouvre, elle aurait réinitialisé. Existe-t-il un moyen de voir quelles sont les valeurs actuelles de sorte que si sa persiste partout, je puisse revenir aux paramètres d'origine ...
Il existe 3 méthodes principales pour effectuer une recherche insensible à la casse dans Oracle sans utiliser d'index de texte intégral.
En fin de compte, la méthode que vous choisissez dépend de votre situation individuelle; la principale chose à retenir est que pour améliorer les performances, vous devez indexer correctement pour la recherche insensible à la casse.
Vous pouvez forcer toutes vos données à être le même cas en utilisant UPPER()
ou LOWER()
:
select * from my_table where upper(column_1) = upper('my_string');
ou
select * from my_table where lower(column_1) = lower('my_string');
S'il column_1
n'est pas indexé upper(column_1)
ou lower(column_1)
, le cas échéant, cela peut forcer une analyse complète de la table. Pour éviter cela, vous pouvez créer un index basé sur les fonctions .
create index my_index on my_table ( lower(column_1) );
Si vous utilisez LIKE, vous devez concaténer un %
autour de la chaîne que vous recherchez.
select * from my_table where lower(column_1) LIKE lower('my_string') || '%';
Ce SQL Fiddle montre ce qui se passe dans toutes ces requêtes. Notez les plans d'explication, qui indiquent quand un index est utilisé et quand il ne l'est pas.
À partir d'Oracle 10g et plus REGEXP_LIKE()
est disponible. Vous pouvez spécifier le _match_parameter_ 'i'
, afin d'effectuer une recherche insensible à la casse.
Pour l'utiliser comme opérateur d'égalité, vous devez spécifier le début et la fin de la chaîne, qui est indiquée par le carat et le signe dollar.
select * from my_table where regexp_like(column_1, '^my_string$', 'i');
Afin de réaliser l'équivalent de LIKE, ceux-ci peuvent être supprimés.
select * from my_table where regexp_like(column_1, 'my_string', 'i');
Soyez prudent avec cela car votre chaîne peut contenir des caractères qui seront interprétés différemment par le moteur d'expression régulière.
Ce SQL Fiddle vous montre le même exemple de sortie, sauf en utilisant REGEXP_LIKE ().
Le paramètre NLS_SORT régit la séquence de classement pour la commande et les divers opérateurs de comparaison, y compris =
et LIKE. Vous pouvez spécifier un tri binaire, insensible à la casse, en modifiant la session. Cela signifie que chaque requête effectuée dans cette session exécutera des paramètres insensibles à la casse.
alter session set nls_sort=BINARY_CI
Il y a beaucoup d'informations supplémentaires sur le tri linguistique et la recherche de chaînes si vous souhaitez spécifier une autre langue ou effectuer une recherche insensible aux accents à l'aide de BINARY_AI.
Vous devrez également modifier le paramètre NLS_COMP ; citer:
Les opérateurs et clauses de requête exacts qui obéissent au paramètre NLS_SORT dépendent de la valeur du paramètre NLS_COMP. Si un opérateur ou une clause n'obéit pas à la valeur NLS_SORT, telle que déterminée par NLS_COMP, le classement utilisé est BINARY.
La valeur par défaut de NLS_COMP est BINARY; mais, LINGUISTIC spécifie qu'Oracle doit prêter attention à la valeur de NLS_SORT:
Les comparaisons pour toutes les opérations SQL dans la clause WHERE et dans les blocs PL / SQL doivent utiliser le tri linguistique spécifié dans le paramètre NLS_SORT. Pour améliorer les performances, vous pouvez également définir un index linguistique sur la colonne pour laquelle vous souhaitez des comparaisons linguistiques.
Donc, encore une fois, vous devez modifier la session
alter session set nls_comp=LINGUISTIC
Comme indiqué dans la documentation, vous souhaiterez peut-être créer un index linguistique pour améliorer les performances
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') || '%';
au lieu de select * from my_table where lower(column_1) LIKE lower('my_string%');
? Cela donne-t-il un avantage?
regexp_like
, y a-t-il un moyen d'échapper à de telles chaînes? Donnant un exemple, si la chaîne a $, la sortie ne sera pas celle que nous attendons. // cc @Ben et autres, merci de partager.
`
est le personnage d'échappement @bozzmob. Il ne devrait pas y avoir de différence de sortie si la chaîne sur laquelle l'expression régulière fonctionne contient un $
, cela ne peut vous poser de problèmes que si vous avez besoin d'un $
littéral dans votre expression régulière. Si vous avez un problème spécifique, je poserais une autre question si ce commentaire / réponse n'a pas aidé.
vous pouvez peut-être essayer d'utiliser
SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'
WHERE upper(user_name) LIKE UPPER('%ME%')
alors? :)
UPPER
aussi le paramètre d'entrée?
upper
fonction vous perdez l'index, avez-vous une idée de comment faire une recherche en utilisant l'index?
Depuis Oracle 12c R2, vous pouvez utiliser COLLATE operator
:
L'opérateur COLLATE détermine le classement d'une expression. Cet opérateur vous permet de remplacer le classement que la base de données aurait dérivé pour l'expression à l'aide de règles de dérivation de classement standard.
L'opérateur COLLATE prend un argument, collation_name, pour lequel vous pouvez spécifier un classement nommé ou un pseudo-classement. Si le nom du classement contient un espace, vous devez placer le nom entre guillemets doubles.
Démo:
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')
%
dans le premier argument du second neNLSSORT
sont pas censés être des caractères génériques, non? Ils confondent en quelque sorte.