Use um SQLCLR UDT. Isso pode funcionar, embora não esteja claro se ele apresenta um ganho líquido em comparação com a abordagem descrita acima.
Sim, um SQLCLR UDT pode ter seus operadores de comparação substituídos por algoritmos customizados. Isso lida com situações em que o valor está sendo comparado a outro valor que já é do mesmo tipo personalizado ou que precisa ser convertido implicitamente. Isso deve lidar com o filtro de faixa em uma WHERE
condição.
Com relação à classificação da UDT como um tipo de coluna regular (não uma coluna calculada), isso só é possível se a UDT for "ordenada por byte". Ser "ordenado por byte" significa que a representação binária da UDT (que pode ser definida na UDT) é classificada naturalmente na ordem apropriada. Supondo que a representação binária seja tratada de maneira semelhante à abordagem descrita acima para a coluna VARCHAR (50) que possui segmentos de comprimento fixo preenchidos, que se qualificariam. Ou, se não fosse fácil garantir que a representação binária fosse ordenada naturalmente da maneira correta, você poderia expor um método ou propriedade da UDT que produza um valor que seria ordenado corretamente e, em seguida, criar uma PERSISTED
coluna computada nessa método ou propriedade. O método precisa ser determinístico e marcado como IsDeterministic = true
.
Os benefícios dessa abordagem são:
- Não há necessidade de um campo "valor original".
- Não é necessário chamar um UDF para inserir os dados ou comparar valores. Supondo que o
Parse
método da UDT capte o P7B18
valor e o converta, você poderá simplesmente inserir os valores naturalmente como P7B18
. E com o método implícito de conversão definido na UDT, a condição WHERE também permitiria usar simplesmente P7B18`.
As conseqüências dessa abordagem são:
- Simplesmente selecionar o campo retornará a representação binária, se você estiver usando o UDT ordenado por bytes como o tipo de dados da coluna. Ou, se estiver usando uma
PERSISTED
coluna computada em uma propriedade ou método da UDT, você obterá a representação retornada pela propriedade ou método. Se você quiser o P7B18
valor original , precisará chamar um método ou propriedade da UDT codificada para retornar essa representação. Como você precisa substituir o ToString
método de qualquer maneira, esse é um bom candidato para fornecer isso.
Não está claro (pelo menos para mim, agora que não testei esta parte) o quão fácil / difícil seria fazer alterações na representação binária. Alterar a representação classificada e armazenada pode exigir a remoção e a inclusão novamente do campo. Além disso, a eliminação do Assembly que contém a UDT falharia se usada de qualquer maneira, portanto, você deve garantir que não haja mais nada no Assembly além deste UDT. Você pode ALTER ASSEMBLY
substituir a definição, mas existem algumas restrições nisso.
Por outro lado, o VARCHAR()
campo são dados desconectados do algoritmo, portanto, seria necessário apenas atualizar a coluna. E se houver dezenas de milhões de linhas (ou mais), isso poderá ser feito em uma abordagem em lotes.
Implemente a biblioteca ICU que realmente permite fazer essa classificação alfanumérica. Embora altamente funcional, a biblioteca vem apenas em duas linguagens: C / C ++ e Java. O que significa que você pode precisar fazer alguns ajustes para que funcione no Visual C ++, ou existe a chance de que o código Java possa ser convertido para MSIL usando o IKVM . Existem um ou dois projetos paralelos do .NET vinculados nesse site que fornecem uma interface COM que pode ser acessada no código gerenciado, mas acredito que eles não foram atualizados há algum tempo e ainda não os tentei. A melhor aposta aqui seria lidar com isso na camada de aplicativos com o objetivo de gerar chaves de classificação. As chaves de classificação seriam salvas em uma nova coluna de classificação.
Esta pode não ser a abordagem mais prática. No entanto, ainda é muito legal que essa capacidade exista. Forneci uma explicação mais detalhada de um exemplo disso na seguinte resposta:
Existe um agrupamento para classificar as seguintes cadeias na seguinte ordem 1,2,3,6,10,10A, 10B, 11?
Mas o padrão tratado nessa questão é um pouco mais simples. Para um exemplo que mostra que o tipo de padrão tratado nesta pergunta também funciona, vá para a seguinte página:
Demonstração de agrupamento na UTI
Em "Configurações", defina a opção "numérico" como "ativado" e todos os outros devem ser definidos como "padrão". Em seguida, à direita do botão "classificar", desmarque a opção "Pontos fortes" e marque a opção "Chaves de classificação". Em seguida, substitua a lista de itens na área de texto "Entrada" pela seguinte lista:
P12B22
P7B18
P12B3
as456456hgjg6786867
P7Bb19
P7BA19
P7BB19
P007B18
P7Bb20
P7Bb19z23
Clique no botão "classificar". A área de texto "Saída" deve exibir o seguinte:
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 .
Observe que as chaves de classificação são estruturadas em vários campos, separados por vírgulas. Cada campo precisa ser classificado de forma independente, para que apresente outro pequeno problema a ser resolvido se for necessário implementá-lo no SQL Server.
P7B12
poderia tornar-seP 07 B 12
, em seguida, (via ASCII)80 07 65 12
, então80076512