Sproc d'encodage sur mesure de SQL Server - existe-t-il un moyen plus simple de procéder ?

StackOverflow https://stackoverflow.com/questions/55340

  •  09-06-2019
  •  | 
  •  

Question

Je me demande simplement s'il existe une meilleure façon de procéder dans SQL Server 2005.

En effet, je prends un originator_id (un nombre compris entre 0 et 99) et un 'next_element' (c'est en réalité juste un compteur séquentiel compris entre 1 et 999 999).Nous essayons de créer un « code » à 6 caractères à partir d’eux.

Le originator_id est multiplié par un million, puis le compteur est ajouté, nous donnant un nombre compris entre 0 et 99 999 999.

Ensuite, nous convertissons cela en une chaîne « base 32 » - une fausse base 32, où nous utilisons en réalité simplement 0-9 et A-Z mais avec quelques-uns des alphanums les plus déroutants supprimés pour plus de clarté (I, O, S, Z) .

Pour ce faire, nous divisons simplement le nombre par puissances de 32, en utilisant à chaque étape le résultat que nous obtenons pour chaque puissance comme indice d'un caractère de notre tableau de caractères sélectionnés.

Thus, an originator ID of 61 and NextCodeElement of 9 gives a code of '1T5JA9'

(61 * 1,000,000) + 9 = 61,000,009
61,000,009 div (5^32 = 33,554,432) =  1 = '1'
27,445,577 div (4^32 =  1,048,576) = 26 = 'T'
   182,601 div (3^32 =     32,768) =  5 = '5'
    18,761 div (2^32 =      1,024) = 18 = 'J'
       329 div (1^32 =         32) = 10 = 'A'
         9 div (0^32 =          1) =  9 = '9'

so my code is 1T5JA9

Auparavant, cet algorithme fonctionnait (sous Delphi), mais maintenant j'ai vraiment besoin de pouvoir le recréer dans SQL Server 2005.Évidemment, je n'ai pas tout à fait les mêmes fonctions que celles que j'ai dans Delphi, mais c'est ma vision de la routine.Cela fonctionne et je peux très bien générer des codes (ou reconstruire les codes dans leurs composants).

Mais cela semble un peu long, et je ne suis pas sûr que l'astuce consistant à sélectionner le résultat d'une division dans un int (c'est-à-dire à le convertir, vraiment) soit nécessairement « correcte » - existe-t-il une meilleure approche SQLS pour ce type de chose ?

CREATE procedure dummy_RP_CREATE_CODE @NextCodeElement int, @OriginatorID int,
  @code varchar(6) output
as
begin
  declare @raw_num int;
  declare @bcelems char(32);
  declare @chr int;

  select @bcelems='0123456789ABCDEFGHJKLMNPQRTUVWXY';
  select @code='';

  -- add in the originator_id, scaled into place
  select @raw_num = (@OriginatorID * 1000000) + @NextCodeElement;

  -- now to convert this to a 6-char code

  -- 5^32
  select @chr = @raw_num / 33554432;
  select @raw_num = @raw_num - (@chr * 33554432);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 4^32
  select @chr = @raw_num / 1048576;
  select @raw_num = @raw_num - (@chr * 1048576);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 3^32
  select @chr = @raw_num / 32768;
  select @raw_num = @raw_num - (@chr * 32768);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 2^32
  select @chr = @raw_num / 1024;
  select @raw_num = @raw_num - (@chr * 1024);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 1^32
  select @chr = @raw_num / 32;
  select @raw_num = @raw_num - (@chr * 32);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 0^32  
  select @code = @code + SUBSTRING(@bcelems, 1 + @raw_num, 1);

  -- that's it!
end;

Je ne suis pas désespérément préoccupé par l'optimisation, à moins que cette méthode ne soit en réalité d'un ordre de grandeur (ou deux) pire que n'importe quelle alternative.

Le code n'est exécuté que par petites rafales, générant peut-être 20 ou 30 codes toutes les 10 minutes environ.En raison de la large plage de nombres, je ne souhaite pas pré-calculer les codes dans un immense tableau (seules de petites plages de la plage globale de codes seront utilisées dans une installation donnée).

Cependant, je suis sûr qu'il existe probablement un moyen plus simple d'obtenir le même résultat, en particulier les divisions et les soustractions.

Toute critique, observation ou suggestion constructive serait la bienvenue.

Était-ce utile?

La solution

Étant donné qu'il s'agit de SQL Server 2005, y a-t-il une raison de ne pas utiliser de procédure stockée CLR ?Vous pouvez alors utiliser le langage CLR de votre choix et ce serait probablement un portage relativement direct de votre code Delphi existant.

Autres conseils

Bien que cela puisse clairement être fait dans SQL Server 2005, je pense qu'il est suffisamment «non-base de données» pour qu'une sorte de routine de langage précompilée de haut niveau ait du sens.

J'ai écrit des DLL pour Interbase/Firebird et des sprocs T-SQL pour SQL Server, mais jamais de routine CLR.Ce sera un exercice intéressant !

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top