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