Use un SQLCLR UDT. Esto podría funcionar, aunque no está claro si presenta una ganancia neta en comparación con el enfoque descrito anteriormente.
Sí, un UDT SQLCLR puede tener sus operadores de comparación anulados con algoritmos personalizados. Esto maneja situaciones en las que el valor se compara con otro valor que ya es el mismo tipo personalizado o uno que necesita convertirse implícitamente. Esto debería manejar el filtro de rango en una WHERE
condición.
Con respecto a la clasificación del UDT como un tipo de columna normal (no una columna calculada), esto solo es posible si el UDT está "ordenado por bytes". Estar "ordenado por bytes" significa que la representación binaria del UDT (que se puede definir en el UDT) naturalmente se ordena en el orden apropiado. Suponiendo que la representación binaria se maneja de manera similar al enfoque descrito anteriormente para la columna VARCHAR (50) que tiene segmentos de longitud fija que están rellenados, eso calificaría. O, si no fuera fácil garantizar que la representación binaria se ordenaría naturalmente de la manera adecuada, podría exponer un método o propiedad del UDT que genere un valor que se ordenaría correctamente, y luego crear una PERSISTED
columna calculada en ese método o propiedad. El método debe ser determinista y marcado como IsDeterministic = true
.
Los beneficios de este enfoque son:
- No es necesario un campo de "valor original".
- No es necesario llamar a un UDF para insertar los datos o comparar valores. Suponiendo que el
Parse
método de UDT toma el P7B18
valor y lo convierte, entonces debería poder simplemente insertar los valores naturalmente como P7B18
. Y con el método de conversión implícito establecido en el UDT, la condición WHERE también permitiría usar simplemente P7B18`.
Las consecuencias de este enfoque son:
- Simplemente seleccionando el campo devolverá la representación binaria, si utiliza el UDT ordenado por bytes como el tipo de datos de la columna. O si usa una
PERSISTED
columna calculada en una propiedad o método del UDT, obtendrá la representación devuelta por la propiedad o el método. Si desea el P7B18
valor original , debe llamar a un método o propiedad del UDT que está codificado para devolver esa representación. Como debe anular el ToString
método de todos modos, es un buen candidato para proporcionarlo.
No está claro (al menos para mí en este momento, ya que no he probado esta parte) lo fácil / difícil que sería hacer cualquier cambio en la representación binaria. Cambiar la representación ordenada almacenada puede requerir soltar y volver a agregar el campo. Además, dejar caer el ensamblaje que contiene el UDT fallará si se usa de cualquier manera, por lo que debe asegurarse de que no haya nada más en el ensamblaje además de este UDT. Puede ALTER ASSEMBLY
reemplazar la definición, pero hay algunas restricciones al respecto.
Por otro lado, el VARCHAR()
campo son datos que están desconectados del algoritmo, por lo que solo requeriría actualizar la columna. Y si hay decenas de millones de filas (o más), eso se puede hacer en un enfoque por lotes.
Implemente la biblioteca ICU que realmente permite hacer esta clasificación alfanumérica. Si bien es altamente funcional, la biblioteca solo viene en dos idiomas: C / C ++ y Java. Lo que significa que es posible que necesite hacer algunos ajustes para que funcione en Visual C ++, o existe la posibilidad de que el código Java se pueda convertir a MSIL usando IKVM . Hay uno o dos proyectos secundarios .NET vinculados en ese sitio que proporcionan una interfaz COM a la que se puede acceder en código administrado, pero creo que no se han actualizado en un tiempo y no los he probado. La mejor opción aquí sería manejar esto en la capa de la aplicación con el objetivo de generar claves de clasificación. Las claves de clasificación se guardarían en una nueva columna de clasificación.
Este podría no ser el enfoque más práctico. Sin embargo, todavía es genial que exista tal habilidad. Proporcioné un recorrido más detallado de un ejemplo de esto en la siguiente respuesta:
¿Hay una clasificación para ordenar las siguientes cadenas en el siguiente orden 1,2,3,6,10,10A, 10B, 11?
Pero el patrón que se trata en esa pregunta es un poco más simple. Para ver un ejemplo que muestra que el tipo de patrón que se trata en esta pregunta también funciona, vaya a la siguiente página:
Demostración de colación de UCI
En "Configuración", establezca la opción "numérica" en "on" y todos los demás deben configurarse en "predeterminado". Luego, a la derecha del botón "ordenar", desmarque la opción para "puntos fuertes de diferencia" y marque la opción para "ordenar claves". Luego reemplace la lista de elementos en el área de texto "Entrada" con la siguiente lista:
P12B22
P7B18
P12B3
as456456hgjg6786867
P7Bb19
P7BA19
P7BB19
P007B18
P7Bb20
P7Bb19z23
Haga clic en el botón "ordenar". El área de texto "Salida" debería mostrar lo siguiente:
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 .
Tenga en cuenta que las claves de clasificación están estructuradas en múltiples campos, separados por comas. Cada campo debe clasificarse de forma independiente, por lo que presenta otro pequeño problema para resolver si necesita implementar esto en SQL Server.
P7B12
podría convertirseP 07 B 12
, entonces (a través de ASCII)80 07 65 12
, entonces80076512