2010-11-12 4 views
40

In SQL Server 2008 habe ich eine Tabelle mit dem Namen Zone mit einer Spalte ZoneReference varchar(50) not null als Primärschlüssel.SQL WHERE-Klausel, die Werte mit abschließenden Leerzeichen übereinstimmt

Wenn ich die folgende Abfrage ausführen:

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

ich folgendes Ergebnis:

"WF11XU " 

Hinweis der hintere Raum.

Wie ist das möglich? Wenn das abschließende Leerzeichen tatsächlich in dieser Zeile vorhanden ist, würde ich erwarten, Null Ergebnisse zurückzugeben, also nehme ich an, dass es etwas anderes ist, das SQL Server Management Studio seltsam anzeigt.

In C# -Code Aufruf zoneReference.Trim() entfernt es, was darauf hindeutet, dass es eine Art Leerzeichen ist.

Kann jemand helfen?

Antwort

60

Das ist das erwartete Ergebnis: in SQL Server ignoriert der Operator = nachfolgende Leerzeichen beim Vergleich.

SQL Server folgt der ANSI/ISO SQL-92-Spezifikation (Abschnitt 8.2,, Allgemeine Regeln # 3) zum Vergleich von Zeichenfolgen mit Leerzeichen. Der ANSI-Standard erfordert Auffüllen für die Zeichenketten, die in Vergleichen verwandt werden, so dass ihre Längen übereinstimmen, bevor Sie sie vergleichen. Das Auffüllen wirkt sich direkt auf die Semantik von WHERE- und HAVING-Klauselprädikaten und anderen Transact-SQL-Zeichenfolgenvergleichen aus. Zum Beispiel betrachtet Transact-SQL die Zeichenfolgen "abc" und "abc" für die meisten Vergleichsoperationen als gleichwertig.

Die einzige Ausnahme von dieser Regel ist das LIKE-Prädikat. Wenn die rechte Seite eines LIKE-Prädikatausdrucks einen Wert mit einem nachgestellten Leerzeichen enthält, puffert SQL Server die beiden Werte nicht vor dem Vergleich auf die gleiche Länge. Da der Zweck des LIKE-Prädikats per Definition darin besteht, Muster-Suchvorgänge anstelle einfacher Zeichenfolgengleichheitstests zu ermöglichen, verstößt dies nicht gegen den bereits erwähnten Abschnitt der ANSI SQL-92-Spezifikation.

Source

+0

Ich glaube 'WHERE ZoneReference = 'WF11XU' UND DATALENGTH (ZoneReference) = DATALENGTH ('WF11XU')' wird auch funktionieren und könnte schneller sein als 'LIKE' – a1ex07

+0

@MarkByers Ja, ich sehe - ich habe versucht' wo 'WF11XU' wie ZoneReference' und das hat funktioniert! Seltsamer und seltsamer. Trotzdem ist jeder Tag ein Schultag! –

-3

versuchen

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

Sie haben den Punkt etwas verpasst. Der Punkt war, dass ich nicht erwartet hatte, dass die "where" -Klausel mit dieser Aufzeichnung übereinstimmt. –

+0

Ja, ich glaube Neil wusste, wie es geht, er fragte sich nur, warum er das beobachtete Verhalten sah. –

+1

Die down-Stimmen sind ein bisschen hart, nicht wahr? – AGoodDisplayName

2

Ja, Mark korrekt ist. Führen Sie die folgende 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 

Aber die Behauptung über die "wie" Anweisung scheint im obigen Beispiel nicht zu funktionieren. Ausgang:

(1 row(s) affected) 

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

(1 row(s) affected) 


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

(1 row(s) affected) 

EDIT: Um es zu bekommen, arbeiten Sie am Ende setzen könnte:

obwohl
and name <> rtrim(ltrim(name)) 

hässlich.

EDIT2: abovem Kommentare gegeben, wäre die folgende Arbeit:

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

Leerzeichen am Ende nicht immer ignoriert. Ich habe dieses Problem heute erlebt. Meine Tabelle hatte NCHAR-Spalten und wurde mit VARCHAR-Daten verknüpft. Da die Daten in der Tabelle nicht so groß wie das Feld waren, wurden nachfolgende Leerzeichen automatisch von SQL Server hinzugefügt.

Ich hatte eine ITVF (Inline-Tabellenwertfunktion), die Varchar-Parameter nahm. Die Parameter wurden in einem JOIN zur Tabelle mit den NCHAR-Feldern verwendet.

Die Joins sind fehlgeschlagen, da die an die Funktion übergebenen Daten keine abschließenden Leerzeichen enthielten, sondern die Daten in der Tabelle. Warum war das?

Ich war auf DATA TYPE PRECEDENCE stolperte. (Siehe http://technet.microsoft.com/en-us/library/ms190309.aspx)

Beim Vergleichen von Strings verschiedener Typen wird der niedrigere Prioritätstyp vor dem Vergleich in den höheren Prioritätstyp konvertiert. Also wurden meine VARCHAR-Parameter in NCHARs konvertiert. Die NCHARs wurden verglichen und anscheinend waren die Räume signifikant.

Wie habe ich das behoben? Ich habe die Funktionsdefinition geändert, um NVARCHAR-Parameter zu verwenden, die eine höhere Priorität als NCHAR haben. Jetzt wurden die NCHARs automatisch von SQL Server in NVARCHARs geändert und die nachfolgenden Leerzeichen wurden ignoriert.

Warum habe ich nicht einfach eine RTRIM durchgeführt? Beim Testen wurde festgestellt, dass RTRIM die Leistung abbrach und die JOIN-Optimierungen verhinderte, die sonst von SQL Server verwendet wurden.

Warum nicht den Datentyp der Tabelle ändern? Die Tabellen sind bereits auf Kunden-Websites installiert und sie möchten keine Wartungs-Skripte (Zeit + Geld, um DBAs zu bezahlen) ausführen oder uns Zugang zu ihren Maschinen geben (verständlich).

Verwandte Themen