Frage

Ich lief in etwas ein wenig seltsam an diesem Morgen und dachte, dass ich es für Kommentar einreichen würde.

Kann mir jemand erklären, warum die folgende SQL-Abfrage druckt ‚gleich‘ bei der Ausführung gegen SQL 2008. Der db Kompatibilitätsgrad ist auf 100.

if '' = ' '
    print 'equal'
else
    print 'not equal'

Und diese liefert 0:

select (LEN(' '))

Es erscheint automatisch Trimmen der Raum zu sein. Ich habe keine Ahnung, ob dies der Fall in früheren Versionen von SQL Server ist, und ich habe nichts mehr herum sogar Test es.

Ich lief dies in, weil eine Produktions Abfrage falsche Ergebnisse zurückkehrt. Ich kann dieses Verhalten nicht irgendwo dokumentiert finden.

Hat jemand irgendwelche Informationen dazu?

War es hilfreich?

Lösung

varchars und Gleichheit sind dornige in TSQL. Die LEN Funktion sagt:

  

Gibt die Anzahl der Zeichen, anstatt die Anzahl von Bytes, von dem angegebenen String-Ausdruck, ohne nachgestellte Leerzeichen .

Sie müssen DATALENGTH verwenden, um eine wahre byte Zählung der Daten in Frage zu kommen. Wenn Sie Unicode-Daten haben, beachten Sie, dass der Wert, den Sie in dieser Situation erhalten nicht die gleiche wie die Länge des Textes sein.

print(DATALENGTH(' ')) --1
print(LEN(' '))        --0

Wenn es um die Gleichheit von Ausdrücken kommt, werden die beiden Strings im Vergleich zur Gleichstellung wie folgt aus:

  • Get Shorter Zeichenfolge
  • Pad mit Leerzeichen , bis Länge gleich, dass die längeren Zeichenfolge
  • Vergleichen Sie die beiden

Es ist die mittlere Stufe, die zu unerwarteten Ergebnissen verursacht - nach diesem Schritt werden Sie effektiv Leerzeichen gegen Leerzeichen Vergleich -. Daher sind sie gleich zu sehen sein

LIKE benimmt ich besser als = in der Situation „Rohlinge“, weil es führt kein Auffüllen mit Leerzeichen auf dem Muster, das Sie zu passen versuchen:

if '' = ' '
print 'eq'
else
print 'ne'

geben eq während:

if '' LIKE ' '
print 'eq'
else
print 'ne'

geben ne

Vorsicht mit LIKE obwohl: Es ist nicht symmetrisch ist: es behandelt im Muster Leerzeichen als signifikanten Hinter (RHS), aber nicht das Spiel Ausdruck (LHS). Im Folgenden wird genommen von hier :

declare @Space nvarchar(10)
declare @Space2 nvarchar(10)

set @Space = ''
set @Space2 = ' '

if @Space like @Space2
print '@Space Like @Space2'
else
print '@Space Not Like @Space2'

if @Space2 like @Space
print '@Space2 Like @Space'
else
print '@Space2 Not Like @Space'

@Space Not Like @Space2
@Space2 Like @Space

Andere Tipps

Der Operator = ist T-SQL ist nicht so viel „gleich“ wie es ist „sind der gleiche Wort / Satz, nach der Zusammenstellung des Kontexts des Ausdrucks“ und LEN ist „die Anzahl der Zeichen in dem Wort / Phrase." Keine Sortierungen behandeln folgende Leerzeichen als Teil des Wortes / Phrase ihnen vorhergehenden (obwohl sie behandeln führende Leerzeichen als Teil des Strings sie vorangehen).

Wenn Sie zu unterscheiden, ‚this‘ von ‚this‘, sollten Sie nicht den Verwendung „ist das gleiche Wort oder eine Phrase“ Operators, weil ‚dieses‘ und ‚dieses‘ sind das gleiche Wort.

auf dem Weg Beitrag = Arbeiten ist die Idee, dass der String-Gleichheitsoperator auf seine Argumente Inhalte und auf dem Sortierungs Kontext des Ausdrucks abhängen sollte, aber es sollte nicht abhängig von der Art der Argumente, wenn sie beide String-Typen.

Die natürliche Sprache Begriff „diese sind das gleiche Wort“ ist normalerweise nicht präzise genug, um wie = durch einen mathematischen Operator erfasst werden, und es gibt kein Konzept der String-Typ in natürlicher Sprache. Kontext (dh Sortierungs) zählt (und existiert in natürlicher Sprache) und ist ein Teil der Geschichte, und zusätzliche Eigenschaften (einige, die schrulligen scheinen) sind Teil der Definition von =, um es wohldefiniert in der unnatürlichen Welt zu machen Daten.

Auf dem Typ Frage, würden Sie nicht Worte ändern wollen, wenn sie in verschiedenen String-Typen gespeichert sind. Zum Beispiel kann die Typen VARCHAR (10), CHAR (10) und CHAR (3) können alle Halte Darstellungen des Wortes 'Katze', und? = ‚Cat‘ sollte lassen Sie uns, wenn ein Wert von jedem dieser Arten hält das Wort ‚Katze‘ (mit Fragen des Falles und Akzente durch die Sortierungs bestimmt) entscheiden.

Antwort auf JohnFx Kommentar:

Siehe Mit char und varchar Daten in der Onlinedokumentation. Zitiert von dieser Seite, Hervorhebung von mir:

  

Jeder char und varchar Datenwert hat eine Sortierung. Sortierungen definieren   Attribute wie die Bitmuster der einzelnen Zeichen repräsentieren verwendet wird,    Vergleichsregeln , und die Empfindlichkeit zu Fall oder Akzentuierung.

stimme ich es einfacher sein könnte zu finden, aber es ist dokumentiert.

Bemerkenswert ist auch, dass SQL Semantik, wo = hat mit den Daten der realen Welt zu tun und dem Kontext des Vergleichs (wie etwa Bits Gegensatz zu etwas auf dem Computer gespeichert) hat für ein langen Teil von SQL gewesen Zeit. Die Prämisse von RDBMS und SQL ist die getreue Darstellung von Daten der realen Welt, damit seine Unterstützung für Sortierungen viele Jahre vor ähnlichen Ideen (wie Culture) trat in das Reich der Algol-ähnliche Sprachen. Die Prämisse dieser Sprachen (zumindest bis vor kurzem) war zur Problemlösung in der Technik, nicht das Management von Geschäftsdaten. (Vor kurzem hat die Verwendung von ähnlichen Sprachen in nicht-technischen Anwendungen wie Suche macht einige Einbrüche, aber Java, C #, und so weiter kämpft noch immer mit ihren nicht-businessy Wurzeln.)

Meiner Meinung nach ist es nicht fair, SQL zu kritisieren, anders zu sein „die meisten Programmiersprachen.“ SQL wurde entwickelt, einen Rahmen für die Geschäftsdatenmodellierung zu unterstützen, die von der Entwicklung sehr unterschiedlich ist, so dass die Sprache ist anders (und besser für das Ziel).

Heck, wenn wurde SQL zuerst angegeben, haben einige Sprachen haben keine integrierte String-Typ. Und noch in einigen Sprachen entspricht der Bediener zwischen Strings keine Zeichendaten überhaupt vergleichen zu können, sondern vergleicht Referenzen! Es würde mich nicht überraschen, wenn in einem anderen Jahrzehnt oder zwei, die Idee, dass == ist kulturabhängig die Norm wird.

Ich fand dieses Blog Artikel , die das Verhalten beschreibt und erklärt, warum.

  

Der SQL-Standard erfordert, dass die Zeichenfolge   Vergleiche, effektiv, Pad die   kürzere Zeichenfolge mit Leerzeichen.   Dies führt zu dem überraschenden Ergebnis   dass N ‚‘ = N‘ '(die leere Zeichenkette   gleich eine Reihe von einem oder mehreren Raum   Zeichen) und allgemein jede   String gleich eine andere Zeichenfolge, wenn sie   unterscheiden sich nur durch Leerzeichen. Diese   ein Problem in manchen Kontexten sein kann.

Weitere Informationen auch in MSKB316626

Es gab eine ähnliche Frage vor einiger Zeit, wo ich in ein ähnliches Problem sah hier

Statt LEN ( ' '), die Verwendung DATALENGTH ('') -., Dass Sie den richtigen Wert gibt

Die Lösungen wurden eine LIKE-Klausel verwenden, wie in meiner Antwort dort erklärt, und / oder er gibt eine zweite Bedingung in der WHERE-Klausel DATALENGTH zu überprüfen.

Haben Sie einen Lese dieser Frage und Links drin.

Um einen Wert zu einem wörtlichen Raum zu vergleichen, können Sie auch diese Technik als Alternative zu der Aussage LIKE:

IF ASCII('') = 32 PRINT 'equal' ELSE PRINT 'not equal'

Manchmal hat man mit Leerzeichen in Daten beschäftigen, mit oder ohne andere Zeichen, obwohl die Idee der Verwendung von Null ist besser - aber nicht immer brauchbar. Ich habe in der beschriebenen Situation laufen und gelöst es so aus:

... where ( '>' + @space + '<') <> ( '>' + @ space2 + '<')

Natürlich würden Sie, dass fpr große Menge an Daten nicht tun, aber es funktioniert schnell und einfach für einige hundert Zeilen ...

Herbert

Wie verschiedene Datensätze auf ausgewählten Feldern mit char / varchar auf SQL Server: Beispiel:

declare @mayvar as varchar(10)

set @mayvar = 'data '

select mykey, myfield from mytable where myfield = @mayvar

erwartet

mykey (int) | myfield (varchar10)

1 | 'Data'

erhalten

mykey | myfield

1 | 'Data' 2 | 'Data'

auch wenn ich Schreib select mykey, myfield from mytable where myfield = 'data' (ohne abschließende blank) Ich erhalte die gleichen Ergebnisse.

, wie ich gelöst? In diesem Modus:

select mykey, myfield
from mytable
where myfield = @mayvar 
and DATALENGTH(isnull(myfield,'')) = DATALENGTH(@mayvar)

und wenn es ein Index auf myfield ist, wird es in jedem Fall verwendet werden.

Ich hoffe, es wird hilfreich sein.

Eine andere Möglichkeit ist es, in einen Zustand zurück zu setzen, dass der Raum Wert hat. zB: Ersetzen Sie den Raum mit einem Charakter wie die bekannten _

if REPLACE('hello',' ','_') = REPLACE('hello ',' ','_')
    print 'equal'
else
    print 'not equal'

Rückgabe: nicht gleich

Nicht ideal, und wahrscheinlich langsam, aber ist ein weiterer schneller Weg nach vorne, wenn schnell benötigt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top