Sproc di "codifica" su misura di SQL Server: esiste un modo più accurato per farlo?

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

  •  09-06-2019
  •  | 
  •  

Domanda

Mi sto solo chiedendo se esiste un modo migliore per farlo in SQL Server 2005.

In effetti, sto prendendo un originator_id (un numero compreso tra 0 e 99) e un 'next_element' (in realtà è solo un contatore sequenziale tra 1 e 999.999).Stiamo cercando di creare un "codice" di 6 caratteri da essi.

L'originator_id viene moltiplicato per un milione, quindi viene aggiunto il contatore, dandoci un numero compreso tra 0 e 99.999.999.

Quindi la convertiamo in una stringa "base 32" - una falsa base 32, dove in realtà stiamo usando solo 0-9 e A-Z ma con alcuni degli alfanum più confusi rimossi per chiarezza (I, O, S, Z) .

Per fare ciò, dividiamo semplicemente il numero per potenze di 32, in ogni fase utilizzando il risultato che otteniamo per ciascuna potenza come indice per un carattere dal nostro array di caratteri selezionati.

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

In precedenza questo algoritmo funzionava (in Delphi) ma ora devo davvero poterlo ricreare in SQL Server 2005.Ovviamente non ho a portata di mano le stesse funzioni che ho in Delphi, ma questa è la mia interpretazione della routine.Funziona e posso generare codici (o ricostruire i codici nei loro componenti) perfettamente.

Ma sembra un po' prolisso, e non sono sicuro che il trucco di selezionare il risultato di una divisione in un int (cioè lanciarlo, in realtà) sia necessariamente "giusto" - esiste un approccio SQLS migliore a questo tipo di cosa?

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;

Non sono disperatamente preoccupato per l'ottimizzazione a meno che questo metodo non sia effettivamente un ordine di grandezza (o giù di lì) peggiore di qualsiasi alternativa.

Il codice viene eseguito solo in piccole quantità, generando magari 20 o 30 codici ogni 10 minuti circa.A causa dell'ampia gamma di numeri, non voglio precalcolare i codici in una tabella enorme (in ogni installazione verranno utilizzate solo piccole parti dell'intervallo di codici complessivo).

Tuttavia, sono sicuro che probabilmente esiste un modo più ordinato per ottenere lo stesso risultato, in particolare quelle divisioni e sottrazioni.

Qualsiasi critica, osservazione o suggerimento costruttivo sarà il benvenuto.

È stato utile?

Soluzione

Visto che si tratta di SQL Server 2005, qualche motivo per non utilizzare una procedura memorizzata CLR?Potresti allora usare il tuo linguaggio CLR preferito e probabilmente sarebbe un port relativamente diretto del tuo codice Delphi esistente.

Altri suggerimenti

Sebbene possa essere chiaramente eseguito in SQL Server 2005, penso che sia sufficientemente "non-database" che una sorta di routine linguistica precompilata di alto livello abbia senso.

Ho scritto DLL per Interbase/Firebird e sproc T-SQL per SQL Server, ma mai una routine CLR.Sarà un esercizio interessante!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top