¿Cómo configurar Sqlite3 para que no distinga entre mayúsculas y minúsculas al comparar cadenas?


305

Quiero seleccionar registros de la base de datos sqlite3 por coincidencia de cadenas. Pero si uso '=' en la cláusula where, descubrí que sqlite3 distingue entre mayúsculas y minúsculas. ¿Alguien puede decirme cómo usar cadenas comparando mayúsculas y minúsculas?

Respuestas:


493

Puede usar COLLATE NOCASEen su SELECTconsulta:

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

Además, en SQLite, puede indicar que una columna no distingue entre mayúsculas y minúsculas cuando crea la tabla especificando collate nocaseen la definición de columna (las otras opciones son binary(el valor predeterminado) y rtrim; consulte aquí ). También puede especificar collate nocasecuándo crea un índice. Por ejemplo:

crear tabla de prueba
(
  Text_Value text cotejar nocase
);

insertar en los valores de prueba ('A');
insertar en los valores de prueba ('b');
insertar en los valores de prueba ('C');

crear índice Test_Text_Value_Index
  en prueba (Text_Value cotejar nocase);

Las expresiones involucradas Test.Text_Valueahora deben ser insensibles a mayúsculas y minúsculas. Por ejemplo:

sqlite> seleccione Text_Value de Test donde Text_Value = 'B';
Text_Value      
----------------
si               

sqlite> seleccione Text_Value del orden de prueba por Text_Value;
Text_Value      
----------------
UNA               
si               
C    

sqlite> seleccione Text_Value del orden de prueba por Text_Value desc;
Text_Value      
----------------
C               
si               
UNA               

El optimizador también puede hacer uso del índice para buscar y hacer coincidir mayúsculas y minúsculas en la columna. Puede verificar esto usando el explaincomando SQL, por ejemplo:

sqlite> explique select Text_Value de Test donde Text_Value = 'b';
addr código de operación p1 p2 p3                               
---------------- -------------- ---------- ---------- ---------------------------------
0 Ir a 0 16                                           
1 Entero 0 0                                            
2 OpenRead 1 3 keyinfo (1, NOCASE)                
3 SetNumColumns 1 2                                            
4 cuerdas 8 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 Columna 1 0                                            
12 Devolución de llamada 1 0                                            
13 Siguiente 1 9                                            
14 Cerrar 1 0                                            
15 Detener 0 0                                            
16 Transacción 0 0                                            
17 VerifyCookie 0 4                                            
18 Ir a 0 1                                            
19 Noop 0 0                                            

20
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 (¿seis a 10 veces, aproximadamente?)
DefenestrationDay

10
Según la documentación, añadiendo COLLATE NOCASEal índice no es necesario si el campo en sí ya tiene esta colación definido: " El orden de clasificación predeterminado es el orden de clasificación definido para esa columna en la sentencia CREATE TABLE. "
Heinzi

29
COLLATE NOCASEsolo funcionará con texto ASCII. Una vez que tenga "FIANCÉ" o "voilà" en los valores de su columna, no coincidirá con "prometido" o "VOILA". Después de habilitar la extensión ICU, LIKEno distingue entre mayúsculas y minúsculas , por lo que 'FIANCÉ' LIKE 'fiancé'es cierto, pero 'VOILA' LIKE 'voilà'sigue siendo falso. E ICU + LIKE tiene el inconveniente de no usar el índice, por lo que puede ser lento en tablas grandes.

seleccione div, mayúsculas y minúsculas cuando div = 'fail' luego 'FAIL' más 'PASSED' final, * de las marcas cotejar nocase arriba no funcionó ¿Estoy haciendo algo mal?
Trueno

77
Una cosa a tener en cuenta que me hizo tropezar: select * from tbl where firstname='john' and lastname='doe' COLLATE NOCASEno distingue entre mayúsculas y minúsculas lastname. Para ser sensible a mayúsculas en firstname, escribir lo siguiente: select * from tbl where firstname='john' COLLATE NOCASE and lastname='doe'. Es específico de esa columna, no la wherecláusula completa .
James Toomey

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

55
Si eres como yo y quieres más documentación sobre la Clasificación, puedes encontrarla aquí en esta página: sqlite.org/datatype3.html Solo desplázate hacia abajo hasta # 6.0
Será el

47

Puedes hacerlo así:

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

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

"El operador LIKE hace una comparación de coincidencia de patrones. El operando 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 cero o más caracteres en la cadena. Un guión bajo ("_") en el patrón coincide con cualquier carácter individual en la cadena. Cualquier otro carácter coincide con sí mismo o con su equivalente en minúscula / mayúscula (es decir, coincidencia entre mayúsculas y minúsculas ) . (Un error: SQLite solo entiende mayúscula / minúscula para caracteres ASCII. El operador LIKE distingue entre mayúsculas y minúsculas para caracteres unicode que están más allá del rango ASCII. Por ejemplo, la expresión 'a' LIKE 'A' es VERDADERA pero 'æ' LIKE 'Æ'Es falso.)."


@ MM-BB sí, a menos que realicemos el LIKE en una columna que se declara (o indexa) como COLLATE NOCASE, realizará un análisis completo de las filas.
Nick Dandoulakis

1
No es un error, es una limitación documentada. La misma página citada en la respuesta menciona la extensión de la UCI que administra los caracteres unicode. (Quizás no fue el caso en 2009)
stenci

40

Esto no es específico de sqlite pero solo puedes hacer

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

La otra parte de la preocupación por el rendimiento es encontrar las filas coincidentes en la tabla. ¿SQLite3 admite índices basados ​​en funciones? Indizar la columna de búsqueda o expresión (por ejemplo, "SUPERIOR (nombre)") en una situación como esta suele ser una buena idea.
cheduardo

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

1
@ cantidad, sí, mucho.
The Berga

4

Otra opción es crear su propia colación personalizada. Luego puede establecer esa clasificación en la columna o agregarla a sus cláusulas de selección. Se utilizará para ordenar y hacer comparaciones.

Esto se puede usar para hacer 'VOILA' COMO 'voilà'.

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

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


2

Otra opción que puede o no tener sentido en su caso, es tener una columna separada con valores precalificados de su columna existente. Esto se puede completar utilizando la función SQLiteLOWER() , y luego puede realizar coincidencias en esta columna.

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


2

Simplemente, puede usar COLLATE NOCASE en su consulta SELECT:

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

1

Si la columna es de tipo, charentonces debe agregar el valor que está consultando con espacios, consulte esta pregunta aquí . Esto además de usar COLLATE NOCASEo una de las otras soluciones (upper (), etc.).



0

Me está funcionando perfectamente. SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.