:: HDS Consultores TI Servidores | Redes | Programacion | GNU/Linux | PostgreSQL Web: http://hdsconsultores.net Blog: http://codigohds.com Linux User #:320363
El 13 de abril de 2010 14:12, Gunnar Wolf <gw...@gwolf.org> escribió: > Gustavo Rosso dijo [Mon, Mar 22, 2010 at 10:53:18AM -0300]: > >> Parece que me expresé mal, no necesariamente necesito un tipo de > >> datos, pero sería genial que así se pudiera generar, lo que deseo es > >> poder tener algo como un character varing de longitud 3 que sea > >> autoincrementable, osea que se baya generando de la siguiente manera > >> 001, 002, 003..... 012,013,014, ... etc debido a que necesito grabar > >> esos 3 caracteres y como serial no me conserva los ceros, quizas otra > >> solucion seria poder guardar el serial pero con los ceros delante cosa > >> que yo al traerlos o exportarlos siempre pueda manipular esos 3 > >> caracteres... me explico??? > > > > Un trigger que llame a una funcion antes del insert? > > (Sí, esta es una consulta más bien vieja, pero bueno... Me sorprende > que nadie haya dicho esto hasta ahora ;-) ) > Esta fue la primera respuesta que se le dio: "Eso de poner los rellenar con ceros lo puedes hacer via tu lenguaje o via SQL con PostgreSQL usando lpad(). Te recomiendo que tengas el campo entero o serial y hagas el relleno de ceros con lpad(), Leete esto: http://www.postgresql.org/docs/8.4/static/functions-string.html " Creo que no tiene mucha diferencia con lo que le recomiendas.... > > Gustavo, el meollo de esto es para qué quieres _guardarlo_ en ese > formato. Un campo serial es por naturaleza entero, esto agiliza su > manejo interno (ordenamiento, búsqueda, comparación). > > Un campo de tipo entero _no tiene_ representación directa. Esto es, en > la representación física de los datos (en el disco) no aparece el > valor '1', '2', '3', etcétera — Aparece un campo de 32 bits que tiene > el valor numérico en cuestión, pero no de una manera que tú lo puedas > leer. Ilustro, con una conversión bastante simplista. En Ruby: > > def disgrega(palabra) > (0..palabra.size-1).map{|i| palabra[i]} > end > > def suma(arreglo=[]) > return 0 if arreglo.empty? > return arreglo[-1].to_i + 256*suma(arreglo[0..-2]) > end > > La primer función separa una cadena en sus bytes constitutivos: > > >> disgrega('hola') > => [104, 111, 108, 97] > > La segunda función los suma, multiplicando cada posición por 256, para > formar un entero. Esto es, > > >> suma(disgrega('hola')) > => 1752132705 > > Ahora, ¿qué pasa con la representación que buscas guardar? Veamos: > > >> suma(disgrega('001')) > => 3158065 > >> suma(disgrega('002')) > => 3158066 > >> suma(disgrega('003')) > => 3158067 > > Esto porque, claro está, cada '0' vale 48. Entonces, si bien en la > práctica podrías lograr tu propósito representando enteros como > cadenas, sería altamente ineficiente. Las comparaciones funcionarían, > aunque dejarían huecos – Por ejemplo: > > >> suma(disgrega('009')) > => 3158073 > >> suma(disgrega('010')) > => 3158320 > > Acá tienes un brinco de 247 (esto es, 256-9, ¿te queda claro por qué? > :-) ) > > Bueno, a lo que iba con todo esto: Te conviene guardar los datos en un > campo entero. A PostgreSQL le es mucho más agradable trabajar con este > tipo de datos, y lo hace rápido y de buena gana. Las cadenas siempre > duelen y lo ponen de mal humor. Y tú no quieres eso. > > Obviamente, quieres manejar el consecutivo formateado en tu > aplicación. Acá, una de dos: O formateas desde Postgres _después_ de > obtener el valor (SELECT lpad(id::text, 3, '0') FROM tabla WHERE ...), > o manejas el valor íntegramente como numérico dentro de Postgres y le > das formato en tu aplicación, al momento de presentarla al usuario > (p.ej. con un sprintf('%03d', id) o su equivalente en tu lenguaje > favorito). > > Pero bueno, en resumen: Te conviene separar el dato de su > presentación. No creo que haya ninguna razón _real_ para que busques > almacenarlo con los ceros precedentes. Sólo al presentarlo al > usuario. > > Saludos, > > -- > Gunnar Wolf • gw...@gwolf.org • (+52-55)5623-0154 / 1451-2244 > -- > TIP 2: puedes desuscribirte de todas las listas simultáneamente > (envía "unregister TuDirecciónDeCorreo" a majord...@postgresql.org) >