2010-09-27 5 views
12

In einem Testfall, den ich geschrieben habe, scheint der String-Vergleich zwischen SQL Server/.NET CLR nicht zu funktionieren.String Vergleichsunterschiede zwischen .NET und T-SQL?

Diese C# -Code:

string lesser = "SR2-A1-10-90"; 
string greater = "SR2-A1-100-10"; 

Debug.WriteLine(string.Compare("A","B")); 
Debug.WriteLine(string.Compare(lesser, greater)); 

Will Ausgang:

-1 
1 

Diese SQL Server-Code:

declare @lesser varchar(20); 
declare @greater varchar(20); 

set @lesser = 'SR2-A1-10-90'; 
set @greater = 'SR2-A1-100-10'; 

IF @lesser < @greater 
    SELECT 'Less Than'; 
ELSE 
    SELECT 'Greater than'; 

Will Ausgang:

Less Than 

Warum der Unterschied?

+0

Berücksichtigen Sie die Groß- und Kleinschreibung? –

+0

Die Fälle sind gleich. Der Unterschied ist, wie jeder die '0' mit '-' behandelt. –

+0

Dies ist ein Unicode-Problem, denke ich. Edit: Vielleicht nicht. Für mich gibt der SQL Server-Code 'Greater than' zurück. Wie lautet die Standardsortierung in der Datenbank, in der Sie sie testen? –

Antwort

10

Dies ist documented here.

Windows-Kollatierungen (z. B. Latin1_General_CI_AS) verwenden Unicode-Sortierregeln. SQL-Sortierungen nicht.

Dadurch wird das Bindestrichzeichen zwischen den beiden unterschiedlich behandelt.

+0

Wählen Sie * aus fn_helpcollations() wo Name wie '% SQL_Latin1_General_CP1_CI_AS%' oder name = 'Latin1_General_CI_AS' – gbn

+0

Die Nicht-Unicode-Sortierung ist anders, verwendet CP 1252. Ich bin sicher, LATIN1 .. tat das gleiche auch ... Nein, tut es nicht .. http://msdn.microsoft.com/en-us/library/ms143515.aspx – gbn

3
  • In SQL verwendet, um Sie varchar, die im Grunde ASCII (je nach Zusammenstellung), die geben wird - vor 0
  • In C# alle Saiten sind Unicode

Die Feinheiten der UTF-xx (C#) vs UCS-2 (SQL Server) sind ziemlich schwierig.

Edit:

ich gepostet zu früh

I "Größer-als" auf SQL Server 2008 mit Sortierung Latin1_General_CI_AS erhalten

Edit 2:

ich auch SELECT ASCII(...) würde versuchen, auf Ihrem Strich. Wenn beispielsweise das SQL-Snippet jemals in einem Word-Dokument enthalten war, ist das - (150) nicht das - (45), das ich in SQL Server kopiert habe, um aus meinen Fragen heraus den Browser zu testen. Siehe CP 1252 (= CP1 = SQL Server-Sprache)

Edit 3: Siehe Martin Smiths Antwort: Die 2 Sortierungen haben unterschiedliche Sortierreihenfolgen.

+0

Ah, ich verstehe. Wenn ich nvarchar (20) verwende, bekomme ich 'Greater Than'. –

+0

Ich bekomme das mit Varchar. Unterscheidet sich Ihre DB-Sortierung von der Server-Sortierung? – gbn

7

Zusätzlich zu der Antwort von gbn können Sie sie mithilfe von CompareOptions.StringSort in C# gleich verhalten (oder mithilfe von StringComparison.Ordinal). Dies behandelt Symbole so, dass sie vor alphanumerischen Symbolen auftreten, also "-" < "0".

Unicode vs ASCII erklärt jedoch nichts, da die Hexadezimalcodes für die ASCII-Codepage wortwörtlich in die Unicode-Codepage übersetzt werden: "-" ist 002D (45), während "0" 0030 (48) ist.

Was passiert, ist, dass .NET standardmäßig "linguistisches" Sortieren verwendet, das auf einer nicht-ordinalen Ordnung und Gewichtung basiert, die von der angegebenen oder aktuellen Kultur auf verschiedene Symbole angewendet wird. Dieser linguistische Algorithmus erlaubt es beispielsweise, "résumé" (buchstabiert mit Akzenten) unmittelbar nach "resume" (buchstabiert ohne Akzente) in einer sortierten Liste von Wörtern zu erscheinen, da "é" eine gebrochene Ordnung unmittelbar nach "e" und erhält lange vor "f". Es erlaubt auch, dass "Zusammenarbeit" und "Zusammenarbeit" eng zusammengefügt werden, da das Strichsymbol ein niedriges "Gewicht" erhält; es ist nur als der absolute letzte Tiebreaker beim Sortieren von Wörtern wie "Bits", "Bit's" und "Bit-Shift" (die in dieser Reihenfolge erscheinen würden) relevant.

Sogenannte ordinale Sortierung (streng nach Unicode-Werten, mit oder ohne Berücksichtigung der Groß-/Kleinschreibung) führt zu sehr unterschiedlichen und manchmal unlogischen Ergebnissen, da Buchstabenvarianten in ASCII/Unicode-Ordinalzahlen normalerweise deutlich hinter dem einfachen undekorierten lateinischen Alphabet erscheinen. während Symbole davor auftreten. Zum Beispiel kommt "é" hinter "z" und so würden die Wörter "resume", "rosin", "Rubel", "resumé" in dieser Reihenfolge sortiert. "Bits", "Bit-Shift", "Biter", "Bits" werden in dieser Reihenfolge sortiert, wenn der Apostroph zuerst kommt, gefolgt vom Bindestrich, dann der Buchstabe "e", dann der Buchstabe "s". Keiner von diesen scheint logisch aus einer "natürlichen Sprache" Perspektive.

+0

Code-Seite betrifft nur Zeichen> 127, nein? – gbn

+0

Kühl. Mit dem 'CompareOption.StringSort' kann ich meinen Test mit den aktuellen Sortiereinstellungen der Datenbank ausführen. –

+0

@gbn - Technisch ja. Es ist auch C#, das scheint "falsch" zu sortieren; Ohne StringSort kommen Symbole nach alphanumerischen Zeichen. Ich werde bearbeiten. – KeithS

0

Mehrere gute Antworten bereits auf, warum dies passiert, aber ich bin sicher, andere möchten nur den C# -Code kennen, um die Sammlung in der gleichen Reihenfolge wie SQL Server zu iterieren. Ich habe die folgenden Arbeiten am besten gefunden. "Ordinal" umgeht das Bindestrichproblem, während "IgnoreCase" auch den SQL Server-Standard widerzuspiegeln scheint.

Debug.WriteLine(string.Compare(lesser, greater, StringComparison.OrdinalIgnoreCase)); 
Verwandte Themen