Me deparei com este post ( Qual é a diferença entre tinyint, smallint, mediumint, bigint e int no MySQL? ) E percebi que o PostgreSQL não oferece suporte a inteiros sem sinal.
Alguém pode ajudar a explicar porque é assim?
Na maioria das vezes, eu uso inteiros sem sinal como chave primária com incremento automático no MySQL. Nesse projeto, como posso superar isso quando transporto meu banco de dados do MySQL para o PostgreSQL?
Obrigado.
postgresql
unsigned-integer
Adrian Hoe
fonte
fonte
serial
(1 a 2147483647) oubigserial
(1 a 9223372036854775807). Um inteiro de 64 bits assinado provavelmente oferece espaço mais do que suficiente.Respostas:
Já foi respondido porque o postgresql carece de tipos não assinados. No entanto, gostaria de sugerir o uso de domínios para tipos não assinados.
http://www.postgresql.org/docs/9.4/static/sql-createdomain.html
O domínio é como um tipo, mas com uma restrição adicional.
Para um exemplo concreto, você pode usar
Aqui está o que o psql oferece quando tento abusar do tipo.
fonte
Não está no padrão SQL, então a necessidade geral de implementá-lo é menor.
Ter muitos tipos de inteiros diferentes torna o sistema de resolução de tipo mais frágil, então há alguma resistência em adicionar mais tipos à mistura.
Dito isso, não há razão para que isso não possa ser feito. É apenas muito trabalho.
fonte
to_char
padrão.Você pode usar uma restrição CHECK, por exemplo:
Além disso, o PostgreSQL tem
smallserial
,serial
ebigserial
tipos para incremento automático.fonte
2^32-1
, enquanto os ints assinados podem subir para2^31-1
.NULL
eCHECK
são completamente ortogonais. Você pode terNULL
/NOT NULL
colunas com ou semCHECK
. Apenas observe que, de acordo com a documentação em postgresql.org/docs/9.4/ddl-constraints.html ,CHECK
retornar NULL é avaliado como TRUE, portanto, se você realmente deseja evitar NULLs, use em seuNOT NULL
lugar (ou além deCHECK
).integer
(não sem que eles sejam aleatoriamente positivos ou negativos, pelo menos ..)A conversa sobre DOMAINS é interessante, mas não relevante para a única origem possível dessa questão. O desejo de ints sem sinal é dobrar o intervalo de ints com o mesmo número de bits, é um argumento de eficiência, não o desejo de excluir números negativos, todo mundo sabe como adicionar uma restrição de verificação.
Quando questionado por alguém sobre isso , Tome Lane afirmou:
O que é "POLA"? O Google me deu 10 resultados sem sentido . Não tenho certeza se é pensamento politicamente incorreto e, portanto, censurado. Por que este termo de pesquisa não produziria nenhum resultado? Tanto faz.
Você pode implementar ints não assinados como tipos de extensão sem muitos problemas. Se você fizer isso com funções C, não haverá nenhuma penalidade de desempenho. Você não precisará estender o analisador para lidar com literais porque o PgSQL tem uma maneira fácil de interpretar strings como literais, basta escrever '4294966272' :: uint4 como seus literais. Casts também não deveriam ser um grande negócio. Você nem mesmo precisa fazer exceções de intervalo, você pode apenas tratar a semântica de '4294966273' :: uint4 :: int como -1024. Ou você pode lançar um erro.
Se eu quisesse, eu teria feito. Mas como estou usando Java no outro lado do SQL, para mim tem pouco valor, já que o Java também não tem esses inteiros sem sinal. Portanto, não ganho nada. Já fico chateado se obtiver um BigInteger de uma coluna bigint, quando deveria caber em longa.
Outra coisa, se eu tivesse a necessidade de armazenar tipos de 32 ou 64 bits, posso usar PostgreSQL int4 ou int8 respectivamente, apenas lembrando que a ordem natural ou aritmética não funcionará de forma confiável. Mas o armazenamento e a recuperação não são afetados por isso.
Aqui está como posso implementar um int8 simples sem sinal:
Primeiro vou usar
as 2 funções mínimas
uint8_in
euint8_out
devo primeiro definir.precisa implementar isso em C uint8_funcs.c. Então, vou usar o exemplo complexo a partir daqui e torná-lo simples:
bem, ou você pode simplesmente descobrir que está pronto .
fonte
De acordo com a documentação mais recente, o inteiro marcado é suportado, mas nenhum inteiro sem sinal na tabela. No entanto, o tipo de série é semelhante ao sem sinal, exceto que começa de 1 e não de zero. Mas o limite superior é o mesmo que chamuscado. Portanto, o sistema realmente não tem suporte não assinado. Conforme apontado por Peter, a porta está aberta para implementar a versão não assinada. O código pode ter que ser muito atualizado, muito trabalho com a minha experiência de trabalho com programação C.
https://www.postgresql.org/docs/10/datatype-numeric.html
fonte
Postgres tem um tipo inteiro não assinado que é desconhecido para muitos:
OID
.Não é um tipo numérico , porém, e tentar fazer qualquer aritmética (ou mesmo operações bit a bit) com ele vai falhar. Além disso, tem apenas 4 bytes (
INTEGER
), não há nenhumBIGINT
tipo sem sinal de 8 bytes ( ) correspondente .Portanto, não é realmente uma boa ideia usar isso você mesmo, e eu concordo com todas as outras respostas que em um projeto de banco de dados Postgresql você deve sempre usar uma coluna
INTEGER
ouBIGINT
para sua chave primária serial - começando no negativo (MINVALUE
) ou permitindo para wrap around (CYCLE
) se você deseja esgotar todo o domínio.No entanto, é bastante útil para a conversão de entrada / saída, como a migração de outro DBMS. Inserir o valor
2147483648
em uma coluna inteira levará a um " ERRO: inteiro fora do intervalo ", enquanto o uso da expressão2147483648::OID
funciona perfeitamente.Da mesma forma, ao selecionar uma coluna inteira como texto com
mycolumn::TEXT
, você obterá valores negativos em algum ponto, mas commycolumn::OID::TEXT
você sempre obterá um número natural.Veja um exemplo em dbfiddle.uk .
fonte