2011-12-07 7 views
8

Qualcuno può spiegare le regole per come un intervallo di caratteri jolly, ad esempio [A-D], funziona con una fascicolazione case-sensitive?In che modo la gamma di caratteri jolly di SQL Server, ad esempio [A-D], funziona con le regole di confronto con distinzione tra maiuscole e minuscole?

avrei pensato seguente

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

restituirebbe solo i record che si aprono con un caso superiore A, B, C o D, ed escludere i record che iniziano con una minuscola a, b, c o d.

Tuttavia, in realtà, sembra che vengano restituiti record che iniziano con una lettera maiuscola A ma anche record che iniziano con B o b, C o c e D o d. È come se solo il primo carattere dell'intervallo distingue tra maiuscole e minuscole e i caratteri rimanenti nell'intervallo non fanno distinzione tra maiuscole e minuscole.

D'altra parte, il seguente

WHERE CharColumn LIKE '[ABCD]%'; 

fa restituire solo i record che si aprono con un caso superiore A, B, C o D. Tuttavia avrei pensato [AD] sarebbe equivalente [ABCD].

Ottengo gli stessi risultati in SQL Server 2005 e SQL Server 2008 R2.

Esempio:
(istruzioni INSERT scritti con SQL Server 2008 costruttori di riga per la compattezza Se ogni valore viene dato il proprio istruzione di inserimento lo script funzionerà in 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 
*/ 

risposta

11

Avete bisogno di un confronto binario come indicato nella Md. Elias Hossain's answer.

La spiegazione è che gli intervalli nella sintassi del pattern funzionano sulle regole di ordinamento delle regole di confronto.

From BOL

Nelle ricerche gamma, i caratteri incluso nella gamma può variare a seconda delle regole di ordinamento della collazione.

Così

;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 

Returns

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

Quindi la gamma A-D esclude a ma include altre 3 lettere minuscole sotto un CS collazione.

+0

Grazie, risponde perfettamente alla mia domanda. Stavo cercando di capire la logica dietro i risultati apparentemente arbitrari da una ricerca di distanza. Adesso è molto chiaro. Saluti, Simon. –

3

provare

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

L'utilizzo di regole di confronto con distinzione tra maiuscole e minuscole per le stringhe di ricerca che non rientrano in un intervallo, ad es. questo funzionerebbe:

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 
     ); 

... ma chiaramente non è un approccio accettabile!

Come altri hanno suggerito, utilizzare Latin1_General_BIN per intervalli.

+0

'COLLATE Latin1_General_CS_AS' viene utilizzato durante la creazione della tabella e non funziona, la query fornisce lo stesso risultato (nessuna modifica). –

+0

@ Md.EliasHossain: grazie, non ho eseguito correttamente i test. Ora aggiornato. – onedaywhen

10

Può essere eseguito in entrambi i modi:

a. Utilizzare COLLATE mentre creare la tabella come:

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

b. Utilizzare COLLATE durante la selezione di dati come

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

Grazie, non sapevo che potessi specificare le regole di confronto in una clausola WHERE. Ciò sarà molto utile quando si interrogano database che non ho progettato. Inoltre, non avevo pensato di usare una collation binaria invece di una case sensitive. Cheers, Simon –

+0

Usare 'Latin1_General_BIN' invece di' Latin1_General_CS_AS' ha funzionato per me –

Problemi correlati