2009-06-10 18 views

Respuesta

385

puede utilizar COLLATE NOCASE en su SELECT consulta:..

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE 

Además, en SQLite, puede indicar que una columna no debe tener en cuenta mayúsculas y minúsculas al crear la tabla especificando collate nocase en la definición de columna (las otras opciones son binary (valor predeterminado) y rtrim; ver here). Puede especificar collate nocase cuando también crea un índice. Por ejemplo:

 
create table Test 
(
    Text_Value text collate nocase 
); 

insert into Test values ('A'); 
insert into Test values ('b'); 
insert into Test values ('C'); 

create index Test_Text_Value_Index 
    on Test (Text_Value collate nocase); 

Expresiones con Test.Text_Value ahora debería ser sensible a mayúsculas. Por ejemplo:

 
sqlite> select Text_Value from Test where Text_Value = 'B'; 
Text_Value  
---------------- 
b    

sqlite> select Text_Value from Test order by Text_Value; 
Text_Value  
---------------- 
A    
b    
C  

sqlite> select Text_Value from Test order by Text_Value desc; 
Text_Value  
---------------- 
C    
b    
A    

El optimizador también puede utilizar potencialmente el índice para búsqueda y coincidencia insensible a mayúsculas y minúsculas en la columna. Esto se puede comprobar mediante el comando explain SQL, por ejemplo .:

 
sqlite> explain select Text_Value from Test where Text_Value = 'b'; 
addr    opcode   p1   p2   p3        
---------------- -------------- ---------- ---------- --------------------------------- 
0     Goto   0   16           
1     Integer   0   0            
2     OpenRead  1   3   keyinfo(1,NOCASE)     
3     SetNumColumns 1   2            
4     String8   0   0   b         
5     IsNull   -1   14           
6     MakeRecord  1   0   a         
7     MemStore  0   0            
8     MoveGe   1   14           
9     MemLoad   0   0            
10    IdxGE   1   14   +         
11    Column   1   0            
12    Callback  1   0            
13    Next   1   9            
14    Close   1   0            
15    Halt   0   0            
16    Transaction  0   0            
17    VerifyCookie 0   4            
18    Goto   0   1            
19    Noop   0   0            
+12

Después de (re) crear la tabla con 'COLLATE NOCASE', noté que era _mucho_ más rápido que la consulta WHERE name = 'someone' COLLATE NOCASE. MUCHO más rápido (de seis a 10 veces, ¿aproximadamente?) – DefenestrationDay

+6

De acuerdo con la documentación, no es necesario agregar 'COLLATE NOCASE' al índice si el campo ya tiene esta clasificación definida:" [* La secuencia de clasificación predeterminada es la secuencia de clasificación definido para esa columna en la instrucción CREATE TABLE. *] (http://www.sqlite.org/lang_createindex.html) " – Heinzi

+19

' COLLATE NOCASE' solo funcionará con texto ASCII. Una vez que tenga "FIANCÉ" o "voilà" en los valores de su columna, no coincidirá con "fiancé" o "VOILA". Después de habilitar la extensión de la ICU, ['LIKE' no distingue entre mayúsculas y minúsculas] (http://www.sqlite.org/src/artifact?ci=trunk&filename=ext/icu/README.txt), por lo que' 'FIANCÉ' LIKE ' fiancé'' es cierto, pero ''VOILA 'LIKE' voilà'' sigue siendo falso. Y ICU + LIKE tiene el inconveniente de no usar el índice, por lo que puede ser lento en las tablas grandes. –

32

Esto no es específico de SQLite, pero sólo se puede hacer

SELECT * FROM ... WHERE UPPER(name) = UPPER('someone') 
+2

¿Hay alguna pérdida de rendimiento al hacer esto? – quantity

+0

La otra parte del problema de rendimiento es encontrar las filas coincidentes en la tabla. ¿Admite SQLite3 los índices basados ​​en funciones? Indexar la columna o expresión de búsqueda (por ejemplo, "UPPER (name)") en una situación como esta suele ser una buena idea. – cheduardo

+9

Tenga cuidado con este, como insinuó cheduardo, SQLite no puede hacer uso de un índice sobre 'nombre' al ejecutar esta consulta. El motor db necesitará escanear por completo todas las filas, convertir todos los campos 'nombre' a mayúsculas y ejecutar la comparación. –

37

Puede hacerlo de esta manera:

SELECT * FROM ... WHERE name LIKE 'someone' 

(No es la solución, pero en algunos casos es muy conveniente)

"COMO ópera tor hace un patrón de comparación . El operando a a la derecha contiene el patrón, el operando de la izquierda contiene la cadena para que coincida con el patrón. Un símbolo de porcentaje ("%") en el patrón coincide con cualquier secuencia de caracteres en la cadena. Un subrayado ("_") en el patrón coincide con cualquier carácter único en la cadena . Cualquier otro carácter coincide sí mismo o que es inferior/superior caso equivalente (es decir, sensible a las mayúsculas de juego). (A ERROR: SQLite solamente entiende mayúsculas/minúsculas para ASCII caracteres El operador LIKE es caso sensible para caracteres Unicode que están más allá del rango ASCII Para ejemplo, la expresión 'a' LIKE 'A' es.. es cierto, pero 'æ' LIKE 'Æ' es FALSO) "

+0

@ MM-BB sí, a menos que realicemos el LIKE en una columna que está declarada (o indexada) como COLLATE NOCASE, hará un escaneo completo de las filas. –

+0

No es un error, es una limitación documentada. La misma página citada en la respuesta menciona la extensión de la ICU que administra los caracteres Unicode. (Tal vez no fue el caso en 2009) – stenci

140
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE 
+3

Si eres como yo y quieres más documentación sobre Collating, puedes encontrarla aquí en esta página: http: //www.sqlite.org/datatype3.html Just scroll hasta # 6.0 – Will

0

Si la columna es de tipo char entonces usted necesita para añadir el valor que está consultando con espacios, por favor refiérase a esta pregunta here.Esto además de usar COLLATE NOCASE o una de las otras soluciones (superior(), etc.).

2

Otra opción es crear su propia intercalación personalizada. Luego puede establecer esa intercalación en la columna o agregarla a sus cláusulas de selección. Se usará para pedidos y comparaciones.

Esto se puede utilizar para hacer 'VOILA' LIKE 'voilà'.

http://www.sqlite.org/capi3ref.html#sqlite3_create_collation

La función de clasificación debe devolver un número entero que es negativo, cero o positivo si la primera cadena es menor que, igual a, o mayor que el segundo, respectivamente.

1

Otra opción que puede o no tener sentido en su caso, es tener realmente una columna separada con valores pre-reducidos de su columna existente. Esto se puede completar con la función SQLite LOWER(), y luego puede realizar la coincidencia en esta columna.

Obviamente, agrega redundancia y una posibilidad de incoherencia, pero si sus datos son estáticos, podría ser una opción adecuada.

0

puede usar la consulta similar para comparar la cadena respectiva con los valores de la tabla.

Seleccione el nombre de la columna de nombre_tabla donde el nombre de la columna sea igual a 'valor de comparación respectivo';

-1

Me funciona perfectamente. SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE

Cuestiones relacionadas