Me encontré con esta publicación ( ¿Cuál es la diferencia entre tinyint, smallint, mediumint, bigint e int en MySQL? ) Y me di cuenta de que PostgreSQL no admite enteros sin signo.
¿Alguien puede ayudar a explicar por qué es así?
La mayoría de las veces, utilizo un entero sin firmar como clave primaria autoincrementada en MySQL. En tal diseño, ¿cómo puedo superar esto cuando transfiero mi base de datos de MySQL a PostgreSQL?
Gracias.
postgresql
unsigned-integer
Adrian Hoe
fuente
fuente
serial
(1 a 2147483647) obigserial
(1 a 9223372036854775807). Un entero de 64 bits con signo probablemente ofrece espacio más que suficiente.Respuestas:
Ya se ha respondido por qué postgresql carece de tipos sin firmar. Sin embargo, sugeriría usar dominios para tipos sin firmar.
http://www.postgresql.org/docs/9.4/static/sql-createdomain.html
El dominio es como un tipo pero con una restricción adicional.
Para un ejemplo concreto, podría usar
Esto es lo que psql da cuando trato de abusar del tipo.
fuente
No está en el estándar SQL, por lo que la necesidad general de implementarlo es menor.
Tener demasiados tipos de enteros diferentes hace que el sistema de resolución de tipos sea más frágil, por lo que existe cierta resistencia a agregar más tipos a la mezcla.
Dicho esto, no hay ninguna razón por la que no se pueda hacer. Es mucho trabajo.
fuente
to_char
patrón.Puede utilizar una restricción CHECK, por ejemplo:
Además, PostgreSQL tiene
smallserial
,serial
ybigserial
tipos de incremento automático.fuente
2^32-1
, mientras que los ints firmados pueden subir2^31-1
.NULL
yCHECK
son completamente ortogonales. Puede tenerNULL
/NOT NULL
columnas con o sinCHECK
. Solo tenga en cuenta que, según la documentación en postgresql.org/docs/9.4/ddl-constraints.html ,CHECK
devolver NULL se evalúa como TRUE, por lo que si realmente desea evitar NULL, utiliceNOT NULL
en su lugar (o además deCHECK
).integer
(no sin que sean aleatoriamente positivas o negativas, al menos ..)La charla sobre DOMINIOS es interesante pero no relevante para el único origen posible de esa pregunta. El deseo de ints sin firmar es duplicar el rango de ints con el mismo número de bits, es un argumento de eficiencia, no el deseo de excluir números negativos, todos saben cómo agregar una restricción de verificación.
Cuando alguien le preguntó al respecto , Tome Lane declaró:
¿Qué es el "POLA"? Google me dio 10 resultados que no tienen sentido . No estoy seguro de si es un pensamiento políticamente incorrecto y, por lo tanto, está censurado. ¿Por qué este término de búsqueda no da ningún resultado? Lo que sea.
Puede implementar entradas sin firmar como tipos de extensión sin demasiados problemas. Si lo hace con funciones C, no habrá ninguna penalización de rendimiento. No necesitará extender el analizador para tratar con literales porque PgSQL tiene una manera tan fácil de interpretar cadenas como literales, simplemente escriba '4294966272' :: uint4 como sus literales. Los yesos tampoco deberían ser un gran problema. Ni siquiera necesita hacer excepciones de rango, simplemente puede tratar la semántica de '4294966273' :: uint4 :: int como -1024. O puede lanzar un error.
Si hubiera querido esto, lo habría hecho. Pero como estoy usando Java en el otro lado de SQL, para mí tiene poco valor ya que Java tampoco tiene esos enteros sin firmar. Entonces no gano nada. Ya estoy molesto si obtengo un BigInteger de una columna bigint, cuando debería caber en long.
Otra cosa, si tuviera la necesidad de almacenar tipos de 32 bits o 64 bits, puedo usar PostgreSQL int4 o int8 respectivamente, solo recordando que el orden natural o la aritmética no funcionarán de manera confiable. Pero el almacenamiento y la recuperación no se ven afectados por eso.
Así es como puedo implementar un int8 simple sin firmar:
Primero usaré
las 2 funciones mínimas
uint8_in
yuint8_out
primero debo definir.Necesito implementar esto en C uint8_funcs.c. Entonces uso el ejemplo complejo de aquí y lo hago simple:
ah, bueno, o puede encontrarlo ya hecho .
fuente
De acuerdo con la documentación más reciente, se admite el entero sin signo, pero no el entero sin signo en la tabla. Sin embargo, el tipo de serie es similar a unsigned excepto que comienza desde 1 y no desde cero. Pero el límite superior es el mismo que chamuscado. Entonces, el sistema realmente no tiene soporte sin firmar. Como señaló Peter, la puerta está abierta para implementar la versión sin firmar. Es posible que el código tenga que actualizarse mucho, demasiado trabajo de mi experiencia trabajando con la programación C.
https://www.postgresql.org/docs/10/datatype-numeric.html
fuente
Postgres tiene un tipo entero sin signo que es desconocido para muchos:
OID
.Sin embargo, no es un tipo numérico , y tratar de hacer cualquier aritmética (o incluso operaciones bit a bit) con él va a fallar. Además, son solo 4 bytes (
INTEGER
), no hay unBIGINT
tipo sin firmar de 8 bytes ( ) correspondiente .Por lo tanto, no es realmente una buena idea usar esto usted mismo, y estoy de acuerdo con todas las otras respuestas en que en un diseño de base de datos de Postgresql siempre debe usar una columna
INTEGER
oBIGINT
para su clave principal de serie , que comience en negativo (MINVALUE
) o lo permita to wrap around (CYCLE
) si desea agotar el dominio completo.Sin embargo, es bastante útil para la conversión de entrada / salida, como su migración desde otro DBMS. Insertar el valor
2147483648
en una columna de números enteros dará lugar a un " ERROR: número entero fuera de rango ", mientras que el uso de la expresión2147483648::OID
funciona bien.Del mismo modo, al seleccionar una columna entera como texto con
mycolumn::TEXT
, obtendrá valores negativos en algún momento, pero conmycolumn::OID::TEXT
siempre obtendrá un número natural.Vea un ejemplo en dbfiddle.uk .
fuente