On Wed, 24 Feb 2010 23:23:01 -0300, Alvaro Herrera wrote
> Sebastián Villalba escribió:
> > Efectivamente necesito algo así, que no siga patrón correlativo o 
> > determinado.
> > El único requisito es que la longitud debe ser de 7. Por un antojo el
> > "substring(md5(CURRENT_TIME::time)from 7 for 7)" lo hago a partir de la
> > séptima posición, porque se me ocurrió hacerlo así, pero sin contar con 
> > ningún
> > fundamento teórico.
> 
> Supongo que lo que puedes hacer si te interesa asegurar unicidad es
> convertir el número de la función de Verite en un string de 7
> caracteres.  Claro que tendrías que modificarla, porque con una 
> cadena de largo 7 en hex tienes a lo más 268.435.456 cadenas 
> distintas (16^7), pero la función de Verite retorna 2^32 valores 
> distintos (4 mil millones y fracción)
> 
> Lo otro que podrías hacer es usar 24 dígitos en vez de 16, con lo que
> tienes espacio para 4500 millones de valores; cubrirías todo el espacio
> de Verite y un poco más.  Ahí el único trabajo que tendrías sería
> inventar cómo mapear un número de 32 bits a un string ...

Bueno, yo tengo en un sistemita algo similar, pero que si sigue un orden
correlativo. Necesitaba un código único, alfanumérico de 6 dígitos. 

Lo que hago es codificar un campo serial (para garantizar unicidad) en base 36
(utilizando todas las letras utilizables del alfabeto) con lo que tengo 6^36
(un número muy grande).

Un par de ejemplos de la salida:

seba=# SELECT * FROM generar_codigo();
 generar_codigo 
----------------
 0076A4
(1 fila)

seba=# SELECT * FROM generar_codigo();
 generar_codigo 
----------------
 0076A5
(1 fila)

Por si a alguien le sirve, adjunto el código. Son 2 funciones en plpgsql. 
Saludos!

-
-------------------------------------------
Sebastián Villalba
A. Gestión Informática
Facultad de Cs. Médicas
U.N.C. - Argentina
-------------------------------------------

CREATE OR REPLACE FUNCTION transformar(nro_decimal int, OUT base_36 char) AS $$
BEGIN
  IF nro_decimal = 10 THEN base_36 = 'A';
  ELSIF nro_decimal = 11 THEN base_36 = 'B';
  ELSIF nro_decimal = 12 THEN base_36 = 'C';
  ELSIF nro_decimal = 13 THEN base_36 = 'D';
  ELSIF nro_decimal = 14 THEN base_36 = 'E';
  ELSIF nro_decimal = 15 THEN base_36 = 'F';
  ELSIF nro_decimal = 16 THEN base_36 = 'G';
  ELSIF nro_decimal = 17 THEN base_36 = 'H';
  ELSIF nro_decimal = 18 THEN base_36 = 'I';
  ELSIF nro_decimal = 19 THEN base_36 = 'J';
  ELSIF nro_decimal = 20 THEN base_36 = 'K';
  ELSIF nro_decimal = 21 THEN base_36 = 'L';
  ELSIF nro_decimal = 22 THEN base_36 = 'M';
  ELSIF nro_decimal = 23 THEN base_36 = 'N';
  ELSIF nro_decimal = 24 THEN base_36 = 'O';
  ELSIF nro_decimal = 25 THEN base_36 = 'P';
  ELSIF nro_decimal = 26 THEN base_36 = 'Q';
  ELSIF nro_decimal = 27 THEN base_36 = 'R';
  ELSIF nro_decimal = 28 THEN base_36 = 'S';
  ELSIF nro_decimal = 29 THEN base_36 = 'T';
  ELSIF nro_decimal = 30 THEN base_36 = 'U';
  ELSIF nro_decimal = 31 THEN base_36 = 'V';
  ELSIF nro_decimal = 32 THEN base_36 = 'W';
  ELSIF nro_decimal = 33 THEN base_36 = 'X';
  ELSIF nro_decimal = 34 THEN base_36 = 'Y';
  ELSIF nro_decimal = 35 THEN base_36 = 'Z';
  ELSE base_36 = nro_decimal;
  END IF;
END;
$$ LANGUAGE plpgsql STABLE SECURITY DEFINER;

CREATE OR REPLACE FUNCTION generar_codigo() RETURNS char(6) AS $$
DECLARE
/*
   id_decimal es sel campo serial 
   de la tabla que codifico en base 36 
*/
  id_decimal bigint := nextval('boleta_id_seq');
  cod_boleta varchar(6) := '';
  aux_nro_base_10 int ARRAY[6] := '{}';
  aux_longitud int := 0;
  contador int := 0;
BEGIN
  WHILE id_decimal >= 36 LOOP
    aux_nro_base_10[contador] := id_decimal % 36;
    id_decimal := id_decimal / 36;
    contador := contador + 1;
  END LOOP;
  aux_nro_base_10[contador] = id_decimal;
  FOR i IN REVERSE contador..0 LOOP
    cod_boleta := cod_boleta || transformar(aux_nro_base_10[i]);
  END LOOP;
  aux_longitud := char_length(cod_boleta);
  WHILE aux_longitud < 6 LOOP
    cod_boleta := '0'||cod_boleta;
    aux_longitud := char_length(cod_boleta);
  END LOOP;
  RETURN cod_boleta;
END;
$$ LANGUAGE plpgsql STABLE SECURITY DEFINER;
--
TIP 10: no uses HTML en tu pregunta, seguro que quien responda no podrá leerlo

Responder a