2009-08-24 9 views
0

Ich habe eine Spalte in SQL Server 2005, die eine Versionsnummer als eine Zeichenfolge speichert, nach der ich sortieren möchte. Ich konnte nicht herausfinden, wie diese Spalte zu sortieren ist, obwohl ich vermute, dass es sich um eine benutzerdefinierte Funktion oder einen Vergleichsalgorithmus handeln würde.Benutzerdefinierte Sortierfunktion - von SQL Server

Kann mir jemand in die richtige Richtung zeigen, wo ich anfangen soll? Ich google vielleicht das falsche Zeug.

Prost

Tris

+1

Welches Format ist es genau gespeichert? – gbn

Antwort

2

I separate int Spalten verwenden würde (zum Beispiel MajorCol + MinorCol, wenn Sie Tracking-Dur + Nebenversionen) und so etwas wie

order by MajorCol, MinorCol 

in meiner Abfrage ausführen.

1

ich mit einer beibehaltenen berechneten Spalte, die den String in eine int oder String oder etwas Geeignetes für die Sortierung in dem nativen SQL Server-Sortierprozess aussehen würde - also

'1.1.1.1' -> '001.001.001.001' 
'10.10.10.10' -> '010.010.010.010' 
'1.10.1.10' -> '001.010.001.010' 

So können Sie nach der berechneten Spalte sortieren und die erwarteten Ergebnisse erhalten.

Alternativ können Sie einen solchen Vorgang auch inline verwenden, aber er kann sehr langsam sein. Darüber hinaus sind skalare UDFs extrem langsam.

+0

Ich frage mich, ob das Speichern der Versionsinformationen in separaten int-Spalten der richtige Weg ist. –

0

Erstellen einer SQL CLR-Funktion ist der Weg zu gehen. Sie sind extrem schnell und stark. Es wäre schnell und effektiv, da Sie keinen vorhandenen Code ändern müssten, und Sie könnten alle Informationen angeben, die Sie direkt in Ihren SQL-Anweisungen benötigen.

Die SQL CLR-Funktion könnte eine Eingabezeichenfolge sowie andere Parameter akzeptieren, die angeben, welche Informationen Sie aus der Eingabezeichenfolge extrahieren möchten. Sie können dann die Rückgabewerte der Funktion sortieren.

Insbesondere würde ich eine generische Funktion erstellen, die drei Parameter akzeptiert: eine Eingabezeichenfolge, einen regulären Ausdruck und einen Gruppennamen. Mit dieser Funktion können Sie Ihr Datenbankfeld und einen regulären Ausdruck mit benannten Gruppen direkt in der SQL-Anweisung übergeben.

Die SQL-CLR-Funktion würde eine Regex erstellen, testen Sie es gegen die Saite, und würde letztlich Rückkehr der Wert der angepassten Gruppe oder null, wenn es keine Übereinstimmung oder die Gruppe war nicht angepasst (wenn die Gruppe optional war). Im Idealfall sollten Sie jedem Aufruf den gleichen regulären Ausdruck übergeben (vielleicht als Variable wie @regex), um CLR-Caching des kompilierten regulären Ausdrucks zu nutzen. Das Endergebnis wäre sehr flexibel und schnell.

Reguläre Ausdruckoptionen können inline wie folgt im Muster angegeben werden: "(? Imnsx-imnsx: Teilausdruck)". Siehe: msdn.microsoft.com/en-us/library/yd1hzczs.aspx

Der Code für eine solche Funktion würde wie folgt aussehen:

[SqlFunction(IsDeterministic=true,IsPrecise=true,DataAccess=DataAccessKind.None,SystemDataAccess=SystemDataAccessKind.None)] 
public static SqlString RegexMatchNamedGroup(SqlChars input, SqlString pattern, SqlString group_name) 
    { 
     Regex regex = new Regex(pattern.Value); 
     Match match = regex.Match(new string(input.Value)); 
     if (!match.Success) //return null if match failed 
      return SqlString.Null; 
     if (group_name.IsNull) //return entire string if matched when no group name is specified 
      return match.Value; 
     Group group = match.Groups[group_name.Value]; 
     if (group.Success) 
      return group.Value; //return matched group value 
     else 
      return SqlString.Null; //return null if named group was not matched   
    } 

Ihre SQL-Anweisung könnte dann sortieren auf Teile Ihrer Informationen wie so:

declare @regex nvarchar(2000) = '^(?<Major>\d{1,3})\.(?<Minor>\d{1,3})'; 

select VersionNumber 
from YourTable 
order by 
Cast(RegexMatchNamedGroup(VersionNumber, @regex, 'Major') as int), 
Cast(RegexMatchNamedGroup(VersionNumber, @regex, 'Minor') as int) 
Verwandte Themen