Utilisez un UDT SQLCLR. Cela pourrait fonctionner, bien qu'il ne soit pas clair s'il présente un gain net par rapport à l'approche décrite ci-dessus.
Oui, un UDT SQLCLR peut faire remplacer ses opérateurs de comparaison par des algorithmes personnalisés. Cela gère les situations dans lesquelles la valeur est comparée à une autre valeur qui est déjà du même type personnalisé ou à une valeur qui doit être implicitement convertie. Cela devrait gérer le filtre de gamme dans un WHERE
état.
En ce qui concerne le tri de l'UDT en tant que type de colonne normal (pas une colonne calculée), cela n'est possible que si l'UDT est "ordonné en octets". Être "ordonné par octets" signifie que la représentation binaire de l'UDT (qui peut être définie dans l'UDT) trie naturellement dans l'ordre approprié. En supposant que la représentation binaire est traitée de manière similaire à l'approche décrite ci-dessus pour la colonne VARCHAR (50) qui a des segments de longueur fixe qui sont rembourrés, cela serait admissible. Ou, s'il n'était pas facile de garantir que la représentation binaire serait naturellement ordonnée de la bonne manière, vous pourriez exposer une méthode ou une propriété de l'UDT qui génère une valeur qui serait correctement ordonnée, puis créer une PERSISTED
colonne calculée sur celle-ci. méthode ou propriété. La méthode doit être déterministe et marquée comme IsDeterministic = true
.
Les avantages de cette approche sont:
- Pas besoin d'un champ "valeur d'origine".
- Pas besoin d'appeler un UDF pour insérer les données ou comparer des valeurs. En supposant que la
Parse
méthode de l'UDT prend la P7B18
valeur et la convertit, vous devriez pouvoir simplement insérer les valeurs naturellement comme P7B18
. Et avec la méthode de conversion implicite définie dans l'UDT, la condition WHERE permettrait également d'utiliser simplement P7B18 ».
Les conséquences de cette approche sont:
- Si vous sélectionnez simplement le champ, la représentation binaire sera renvoyée si vous utilisez l'octet UDT ordonné comme type de données de colonne. Ou si vous utilisez une
PERSISTED
colonne calculée sur une propriété ou une méthode de l'UDT, vous obtiendrez alors la représentation renvoyée par la propriété ou la méthode. Si vous souhaitez la P7B18
valeur d' origine , vous devez appeler une méthode ou une propriété de l'UDT codée pour renvoyer cette représentation. Étant donné que vous devez de ToString
toute façon remplacer la méthode, c'est un bon candidat pour fournir cela.
Il n'est pas clair (du moins pour moi en ce moment car je n'ai pas testé cette partie) à quel point il serait facile / difficile d'apporter des modifications à la représentation binaire. La modification de la représentation stockée et triable peut nécessiter la suppression et l'ajout du champ. En outre, la suppression de l'assembly contenant l'UDT échouerait si elle était utilisée de l'une ou l'autre manière, vous devez donc vous assurer qu'il n'y avait rien d'autre dans l'assembly que cet UDT. Vous pouvez ALTER ASSEMBLY
remplacer la définition, mais il existe certaines restrictions à ce sujet.
D'un autre côté, le VARCHAR()
champ est constitué de données déconnectées de l'algorithme et ne nécessiterait que la mise à jour de la colonne. Et s'il y a des dizaines de millions de lignes (ou plus), cela peut être fait dans une approche par lots.
Implémentez la bibliothèque ICU qui permet de faire ce tri alphanumérique. Bien que très fonctionnelle, la bibliothèque n'est disponible qu'en deux langues: C / C ++ et Java. Ce qui signifie que vous devrez peut-être effectuer quelques ajustements pour le faire fonctionner dans Visual C ++, ou il y a de fortes chances que le code Java puisse être converti en MSIL à l'aide d' IKVM . Il existe un ou deux projets côté .NET liés sur ce site qui fournissent une interface COM accessible en code managé, mais je pense qu'ils n'ont pas été mis à jour depuis un certain temps et je ne les ai pas essayés. Le mieux serait ici de gérer cela dans la couche d'application dans le but de générer des clés de tri. Les clés de tri seraient alors enregistrées dans une nouvelle colonne de tri.
Ce n'est peut-être pas l'approche la plus pratique. Cependant, il est toujours très cool qu'une telle capacité existe. J'ai fourni un examen plus détaillé d'un exemple de cela dans la réponse suivante:
Existe-t-il un classement pour trier les chaînes suivantes dans l'ordre suivant 1,2,3,6,10,10A, 10B, 11?
Mais le schéma traité dans cette question est un peu plus simple. Pour un exemple montrant que le type de modèle traité dans cette question fonctionne également, veuillez vous rendre sur la page suivante:
ICU Collation Demo
Sous "Paramètres", définissez l'option "numérique" sur "activé" et toutes les autres doivent être définies sur "par défaut". Ensuite, à droite du bouton "trier", décochez l'option "forces de diff" et cochez l'option "trier les clés". Remplacez ensuite la liste des éléments de la zone de texte "Entrée" par la liste suivante:
P12B22
P7B18
P12B3
as456456hgjg6786867
P7Bb19
P7BA19
P7BB19
P007B18
P7Bb20
P7Bb19z23
Cliquez sur le bouton "trier". La zone de texte "Sortie" doit afficher les éléments suivants:
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 .
Veuillez noter que les clés de tri sont structurées en plusieurs champs, séparés par des virgules. Chaque champ doit être trié indépendamment, ce qui présente un autre petit problème à résoudre si vous devez l'implémenter dans SQL Server.
P7B12
pourrait donc devenirP 07 B 12
(via ASCII)80 07 65 12
, donc80076512