2010-11-12 19 views
40

In SQL Server 2008 ho una tabella denominata Zone con una colonna ZoneReference varchar(50) not null come chiave primaria.Clausola WHERE SQL che corrisponde ai valori con spazi finali

Se eseguo la seguente query:

select '"' + ZoneReference + '"' as QuotedZoneReference 
from Zone 
where ZoneReference = 'WF11XU' 

ottengo il seguente risultato:

"WF11XU " 

nota lo spazio finale.

Com'è possibile? Se lo spazio finale è realmente presente in quella riga, mi aspetto di restituire i risultati di zero, quindi suppongo che sia qualcos'altro che SQL Server Management Studio sta visualizzando in modo strano.

Nel codice C# zoneReference.Trim() viene rimosso, suggerendo che si tratta di una sorta di carattere di spazio vuoto.

Qualcuno può aiutare?

risposta

60

Questo è il risultato previsto: in SQL Server l'operatore = ignora gli spazi finali durante il confronto.

SQL Server segue la specifica ANSI/ISO SQL-92 (Sezione 8.2, Regole generali n. 3) su come confrontare stringhe con spazi. Lo standard ANSI richiede il riempimento per le stringhe di caratteri utilizzate nei confronti in modo che le loro lunghezze corrispondano prima di confrontarle. Il riempimento influisce direttamente sulla semantica dei predicati della clausola WHERE e HAVING e su altri confronti tra stringhe Transact-SQL. Ad esempio, Transact-SQL considera le stringhe 'abc' e 'abc' equivalenti per la maggior parte delle operazioni di confronto.

L'unica eccezione a questa regola è il predicato LIKE. Quando il lato destro di un'espressione di predicato LIKE presenta un valore con uno spazio finale, SQL Server non carica i due valori sulla stessa lunghezza prima che avvenga il confronto. Poiché lo scopo del predicato LIKE, per definizione, è di facilitare le ricerche di modelli piuttosto che i semplici test di uguaglianza delle stringhe, ciò non viola la sezione della specifica ANSI SQL-92 menzionata in precedenza.

Source

+0

Credo che WHERE ZoneReference = 'WF11XU' E DATALENGTH (ZoneReference) = DATALENGTH ('WF11XU') 'funzionerà anche e potrebbe essere più veloce di' LIKE' – a1ex07

+0

@MarkByers Sì, vedo - Ho provato 'dove 'WF11XU' come ZoneReference' e questo ha funzionato! Più strano e più strano. Comunque, ogni giorno è un giorno di scuola! –

-3

provare

select Replace('"' + ZoneReference + '"'," ", "") as QuotedZoneReference from Zone where ZoneReference = 'WF11XU' 
+0

Hai perso leggermente il punto. Il punto era che non mi aspettavo clausole 'where' per abbinare questo record. –

+0

Sì, penso che Neil sapeva come farlo, si è semplicemente chiesto perché stava vedendo il comportamento osservato. –

+1

I voti negativi sono un po 'aspri, vero? – AGoodDisplayName

2

Sì, Mark è corretta. Eseguire il seguente SQL:

create table #temp (name varchar(15)) 
insert into #temp values ('james ') 
select '"' + name + '"' from #temp where name ='james' 
select '"' + name + '"' from #temp where name like 'james' 
drop table #temp 

Tuttavia, l'affermazione relativa all'istruzione "mi piace" sembra non funzionare nell'esempio precedente. Uscita:

(1 row(s) affected) 

----------------- 
"james " 

(1 row(s) affected) 


----------------- 
"james " 

(1 row(s) affected) 

EDIT: Per farlo funzionare, si potrebbe mettere alla fine:

and name <> rtrim(ltrim(name)) 

brutto però.

EDIT2: Visti i commenti abovem, il seguente avrebbe funzionato:

select '"' + name + '"' from #temp where 'james' like name 
5

spazi finali non sono sempre ignorati. Ho riscontrato questo problema oggi. La mia tabella aveva colonne NCHAR e veniva aggiunta ai dati VARCHAR. Poiché i dati nella tabella non erano ampi come il relativo campo, gli spazi finali venivano aggiunti automaticamente da SQL Server.

Avevo un ITVF (funzione con valori di tabella inline) che utilizzava parametri varchar. I parametri sono stati utilizzati in un JOIN alla tabella con i campi NCHAR.

I join non sono riusciti perché i dati passati alla funzione non avevano spazi finali ma i dati nella tabella. Perché era quello?

Mi stavo incastrando su PRECEDENZA DI TIPO DI DATI. (Vedi http://technet.microsoft.com/en-us/library/ms190309.aspx)

Quando si confrontano stringhe di tipi diversi, il tipo di precedenza inferiore viene convertito nel tipo di precedenza più alta prima del confronto. Quindi i miei parametri VARCHAR sono stati convertiti in NCHAR. I NCHAR sono stati confrontati e apparentemente gli spazi erano significativi.

Come ho risolto questo problema? Ho modificato la definizione della funzione per utilizzare i parametri NVARCHAR, che hanno una precedenza più alta di NCHAR. Ora gli NCHAR sono stati modificati automaticamente da SQL Server in NVARCHAR e gli spazi finali sono stati ignorati.

Perché non ho appena eseguito un RTRIM? I test hanno rivelato che RTRIM ha ucciso le prestazioni, impedendo le ottimizzazioni JOIN che altrimenti avrebbe utilizzato SQL Server.

Perché non modificare il tipo di dati della tabella? Le tabelle sono già installate sui siti dei clienti e non vogliono eseguire script di manutenzione (tempo + denaro per pagare i DBA) o darci accesso alle loro macchine (comprensibili).