Verwenden Sie eine SQLCLR-UDT. Dies könnte funktionieren, obwohl es unklar ist, ob es im Vergleich zu dem oben beschriebenen Ansatz einen Nettogewinn darstellt.
Ja, bei einem SQLCLR-UDT können die Vergleichsoperatoren mit benutzerdefinierten Algorithmen überschrieben werden. Dies behandelt Situationen, in denen der Wert entweder mit einem anderen Wert verglichen wird, der bereits denselben benutzerdefinierten Typ hat, oder mit einem Wert, der implizit konvertiert werden muss. Dies sollte den Bereichsfilter in einem WHERE
Zustand behandeln.
In Bezug auf das Sortieren des UDT als regulären Spaltentyp (keine berechnete Spalte) ist dies nur möglich, wenn das UDT "Byte geordnet" ist. "Byte geordnet" bedeutet, dass die binäre Darstellung des UDT (die im UDT definiert werden kann) natürlich in der entsprechenden Reihenfolge sortiert wird. Unter der Annahme, dass die binäre Darstellung ähnlich wie der oben für die Spalte VARCHAR (50) beschriebene Ansatz behandelt wird, bei dem Segmente mit fester Länge aufgefüllt sind, würde dies qualifizieren. Wenn es nicht einfach wäre, sicherzustellen, dass die binäre Darstellung natürlich in der richtigen Reihenfolge angeordnet ist, können Sie eine Methode oder Eigenschaft des UDT verfügbar machen, die einen Wert ausgibt, der ordnungsgemäß geordnet ist, und dann eine PERSISTED
berechnete Spalte darauf erstellen Methode oder Eigenschaft. Die Methode muss deterministisch sein und als gekennzeichnet sein IsDeterministic = true
.
Vorteile dieses Ansatzes sind:
- Kein Feld "Originalwert" erforderlich.
- Sie müssen keine UDF aufrufen, um die Daten einzufügen oder Werte zu vergleichen. Angenommen, die
Parse
Methode des UDT nimmt den P7B18
Wert auf und konvertiert ihn, dann sollten Sie in der Lage sein, die Werte einfach auf natürliche Weise als einzufügen P7B18
. Und mit der im UDT festgelegten impliziten Konvertierungsmethode würde die WHERE-Bedingung auch die Verwendung von einfach P7B18` ermöglichen.
Konsequenzen dieses Ansatzes sind:
- Durch einfaches Auswählen des Felds wird die binäre Darstellung zurückgegeben, wenn der nach Byte geordnete UDT als Spaltendatentyp verwendet wird. Wenn Sie eine
PERSISTED
berechnete Spalte für eine Eigenschaft oder Methode des UDT verwenden, wird die von der Eigenschaft oder Methode zurückgegebene Darstellung angezeigt. Wenn Sie den ursprünglichen P7B18
Wert möchten , müssen Sie eine Methode oder Eigenschaft des UDT aufrufen, die codiert ist, um diese Darstellung zurückzugeben. Da Sie die ToString
Methode ohnehin überschreiben müssen, ist dies ein guter Kandidat dafür.
Es ist unklar (zumindest für mich im Moment, da ich diesen Teil nicht getestet habe), wie einfach / schwierig es wäre, Änderungen an der binären Darstellung vorzunehmen. Das Ändern der gespeicherten, sortierbaren Darstellung erfordert möglicherweise das Löschen und erneute Hinzufügen des Felds. Außerdem würde das Löschen der Assembly, die den UDT enthält, fehlschlagen, wenn sie auf eine der beiden Arten verwendet wird. Sie sollten also sicherstellen, dass sich in der Assembly außer diesem UDT nichts anderes befindet. Sie können ALTER ASSEMBLY
die Definition ersetzen, es gibt jedoch einige Einschränkungen.
Auf der anderen Seite handelt es sich bei dem VARCHAR()
Feld um Daten, die vom Algorithmus getrennt sind, sodass nur die Spalte aktualisiert werden muss. Und wenn es mehrere zehn Millionen Zeilen (oder mehr) gibt, kann dies in einem Stapelansatz erfolgen.
Implementieren Sie die ICU- Bibliothek, die diese alphanumerische Sortierung tatsächlich ermöglicht. Die Bibliothek ist zwar hochfunktional, aber nur in zwei Sprachen verfügbar: C / C ++ und Java. Dies bedeutet, dass Sie möglicherweise einige Änderungen vornehmen müssen, damit es in Visual C ++ funktioniert, oder dass die Möglichkeit besteht, dass der Java-Code mithilfe von IKVM in MSIL konvertiert werden kann . Auf dieser Site sind ein oder zwei .NET-seitige Projekte verlinkt, die eine COM-Schnittstelle bieten, auf die in verwaltetem Code zugegriffen werden kann. Ich glaube jedoch, dass sie seit einiger Zeit nicht mehr aktualisiert wurden und ich sie nicht ausprobiert habe. Am besten ist es, dies in der App-Ebene mit dem Ziel zu behandeln, Sortierschlüssel zu generieren. Die Sortierschlüssel würden dann in einer neuen Sortierspalte gespeichert.
Dies ist möglicherweise nicht der praktischste Ansatz. Es ist jedoch immer noch sehr cool, dass eine solche Fähigkeit existiert. In der folgenden Antwort habe ich ein detaillierteres Beispiel dafür gegeben:
Gibt es eine Sortierung, um die folgenden Zeichenfolgen in der folgenden Reihenfolge zu sortieren: 1,2,3,6,10,10A, 10B, 11?
Das in dieser Frage behandelte Muster ist jedoch etwas einfacher. Ein Beispiel, das zeigt, dass die Art des Musters, mit dem sich diese Frage befasst, auch funktioniert, finden Sie auf der folgenden Seite:
ICU Collation Demo
Setzen Sie unter "Einstellungen" die Option "numerisch" auf "ein" und alle anderen sollten auf "Standard" gesetzt sein. Deaktivieren Sie rechts neben der Schaltfläche "Sortieren" die Option für "Diff-Stärken" und aktivieren Sie die Option für "Sortierschlüssel". Ersetzen Sie dann die Liste der Elemente im Textbereich "Eingabe" durch die folgende Liste:
P12B22
P7B18
P12B3
as456456hgjg6786867
P7Bb19
P7BA19
P7BB19
P007B18
P7Bb20
P7Bb19z23
Klicken Sie auf die Schaltfläche "Sortieren". Der Textbereich "Ausgabe" sollte Folgendes anzeigen:
as456456hgjg6786867
29 4D 0F 7A EA C8 37 35 3B 35 0F 84 17 A7 0F 93 90 , 0D , , 0D .
P7B18
47 0F 09 2B 0F 14 , 08 , FD F1 , DC C5 DC 05 .
P007B18
47 0F 09 2B 0F 14 , 08 , FD F1 , DC C5 DC 05 .
P7BA19
47 0F 09 2B 29 0F 15 , 09 , FD FF 10 , DC C5 DC DC 05 .
P7Bb19
47 0F 09 2B 2B 0F 15 , 09 , FD F2 , DC C5 DC 06 .
P7BB19
47 0F 09 2B 2B 0F 15 , 09 , FD FF 10 , DC C5 DC DC 05 .
P7Bb19z23
47 0F 09 2B 2B 0F 15 5B 0F 19 , 0B , FD F4 , DC C5 DC 08 .
P7Bb20
47 0F 09 2B 2B 0F 16 , 09 , FD F2 , DC C5 DC 06 .
P12B3
47 0F 0E 2B 0F 05 , 08 , FD F1 , DC C5 DC 05 .
P12B22
47 0F 0E 2B 0F 18 , 08 , FD F1 , DC C5 DC 05 .
Bitte beachten Sie, dass die Sortierschlüssel in mehreren Feldern strukturiert sind, die durch Kommas getrennt sind. Jedes Feld muss unabhängig sortiert werden, damit ein weiteres kleines Problem gelöst werden kann, wenn dies in SQL Server implementiert werden muss.
P7B12
könnte esP 07 B 12
dann werden (via ASCII)80 07 65 12
, so80076512