2011-12-07 8 views
8

¿Alguien puede explicar las reglas de cómo un rango de caracteres comodín, por ejemplo [A-D], funciona con una intercalación sensible a mayúsculas y minúsculas?¿Cómo funciona el Rango de caracteres comodín de SQL Server, por ejemplo [A-D], con intercalación de mayúsculas y minúsculas?

habría pensado el siguiente

WHERE CharColumn LIKE '[A-D]%'; 

volvería sólo los registros que comienzan con una letra mayúscula A, B, C o D, y excluir registros que comienzan con una caja inferior a, b, c o re.

Sin embargo, en realidad, parece devolver registros que comienzan con una mayúscula A pero también registros que comienzan con B o b, C o c y D o d. Es como si solo el primer carácter del rango distingue entre mayúsculas y minúsculas y los caracteres restantes del rango no distinguen entre mayúsculas y minúsculas.

Por otro lado, el siguiente

WHERE CharColumn LIKE '[ABCD]%'; 

qué sólo devuelven registros que comienzan con una letra mayúscula A, B, C o D. Sin embargo, habría pensado [AD] sería equivalente a [A B C D].

Obtengo los mismos resultados en SQL Server 2005 y SQL Server 2008 R2.

Ejemplo:
(instrucciones de inserción escriben con Server 2008 constructores de registros de SQL para compacidad Si cada valor se le da su propia instrucción de inserción de la secuencia de comandos funciona en SQL Server 2005.)

CREATE TABLE #TEST_LIKE_Patterns 
    ( 
     ID INT IDENTITY(1,1), 
     CharColumn VARCHAR(100) COLLATE Latin1_General_CS_AS 
    ); 

-------------- 
INSERT INTO #TEST_LIKE_Patterns (CharColumn) 
VALUES ('aaa'), ('aAA'), ('AAA'), ('Aaa'); 
--------------  
INSERT INTO #TEST_LIKE_Patterns (CharColumn) 
VALUES ('bbb'), ('bBB'), ('BBB'), ('Bbb'); 
-------------- 
INSERT INTO #TEST_LIKE_Patterns (CharColumn) 
VALUES ('ccc'), ('cCC'), ('CCC'), ('Ccc'); 
--------------  
INSERT INTO #TEST_LIKE_Patterns (CharColumn) 
VALUES ('ddd'), ('dDD'), ('DDD'), ('Ddd'); 
--------------  
INSERT INTO #TEST_LIKE_Patterns (CharColumn) 
VALUES ('eee'), ('eEE'), ('EEE'), ('Eee'); 
--------------  
INSERT INTO #TEST_LIKE_Patterns (CharColumn) 
VALUES ('fff'), ('fFF'), ('FFF'), ('Fff'); 
-------------- 

-- Raw Data: 
SELECT * 
FROM #TEST_LIKE_Patterns; 

SELECT * 
FROM #TEST_LIKE_Patterns 
WHERE CharColumn LIKE '[A-D]%'; 

-- Results: 
/* 
ID CharColumn 
-------------- 
3 AAA 
4 Aaa 
5 bbb 
6 bBB 
7 BBB 
8 Bbb 
9 ccc 
10 cCC 
11 CCC 
12 Ccc 
13 ddd 
14 dDD 
15 DDD 
16 Ddd 
*/ 


SELECT * 
FROM #TEST_LIKE_Patterns 
WHERE CharColumn LIKE '[ABCD]%';  

-- Results: 
/* 
ID CharColumn 
    -------------- 
3 AAA 
4 Aaa 
7 BBB 
8 Bbb 
11 CCC 
12 Ccc 
15 DDD 
16 Ddd 
*/ 

Respuesta

11

Se necesita una colación binaria como se indica en Md. Elias Hossain's answer.

La explicación es que los rangos en la sintaxis del patrón funcionan fuera de las reglas de orden de clasificación.

From BOL

En las búsquedas por rango, los caracteres incluidos en el alcance puede variar dependiendo de las reglas de clasificación de la colación.

Así

;WITH T(C) AS 
(
SELECT 'A' UNION ALL 
SELECT 'B' UNION ALL 
SELECT 'C' UNION ALL 
SELECT 'D' UNION ALL 
select 'a' union all 
select 'b' union all 
select 'c' union all 
select 'd' 
) 
SELECT * 
FROM T 
ORDER BY C COLLATE Latin1_General_CS_AS 

devoluciones

C 
---- 
a 
A 
b 
B 
c 
C 
d 
D 

lo que el rango A-D excluye a pero incluye los otros 3 letras minúsculas bajo una colación CS.

+0

Gracias, esto responde perfectamente a mi pregunta. Estaba tratando de entender la lógica detrás de los resultados aparentemente arbitrarios de una búsqueda en rango. Está muy claro ahora. Saludos, Simon. –

3

tratar

SELECT * 
FROM #TEST_LIKE_Patterns 
WHERE CharColumn LIKE '[A-D]%' COLLATE Latin1_General_BIN; 
0

El uso de una intercalación de mayúsculas y minúsculas funciona para cadenas de búsqueda que no están en un rango, por ejemplo esto funcionaría:

SELECT * 
    FROM #TEST_LIKE_Patterns 
WHERE (
     CharColumn LIKE 'A%' COLLATE Latin1_General_CS_AS 
     OR CharColumn LIKE 'B%' COLLATE Latin1_General_CS_AS 
     OR CharColumn LIKE 'C%' COLLATE Latin1_General_CS_AS 
     OR CharColumn LIKE 'D%' COLLATE Latin1_General_CS_AS 
     ); 

... pero claramente ese no es un enfoque aceptable.

Como han sugerido otros, use Latin1_General_BIN para rangos.

+0

'COLLATE Latin1_General_CS_AS' se utiliza al crear la tabla y no funciona, su consulta proporciona el mismo resultado (sin cambios). –

+0

@ Md.EliasHossain: gracias, no hice la prueba correctamente. Ahora actualizado. – onedaywhen

10

Se puede hacer de cualquier manera:

a. Utilice COLLATE mientras que crear la tabla como:

CREATE TABLE #TEST_LIKE_Patterns 
( 
    ID INT IDENTITY(1,1), 
    CharColumn VARCHAR(100) COLLATE Latin1_General_BIN 
); 

b. Utilice COLLATE mientras que la selección de datos como

SELECT * 
FROM #TEST_LIKE_Patterns 
WHERE CharColumn LIKE '%[A-D]%' COLLATE Latin1_General_BIN; 
+0

Gracias, no sabía que pudiera especificar la intercalación en una cláusula WHERE. Eso será más útil cuando consulto bases de datos que no he diseñado. Además, no había pensado utilizar una intercalación binaria en lugar de una mayúscula. Saludos, Simon –

+0

Usando 'Latin1_General_BIN' en lugar de' Latin1_General_CS_AS' trabajado para mí –

Cuestiones relacionadas