Como armazenar um inteiro de um byte no PostgreSQL?

14

Na documentação do PostgreSQL, diz-se que tipos de dados inteiros podem ser armazenados em espaço de dois, quatro ou oito bytes. Uma das colunas de uma tabela no meu banco de dados contém um valor inteiro de um byte e eu quero que ele seja armazenado em um tipo de dados de um byte.

  1. Existe uma extensão ou uma maneira de usar o tipo de dados inteiro de um byte no PostgreSQL?
  2. Quantos bytes é NUMERIC (1,0)?
ukll
fonte

Respostas:

16

Não , não há um número inteiro de 1 byte na distribuição padrão do Postgres. Todos os tipos numéricos incorporados do Postgres padrão ocupam 2 ou mais bytes.

Pinguim de extensão

Mas sim , existe a extensão pguint , mantida por Peter Eisentraut, um dos principais desenvolvedores do Postgres. Não faz parte da distribuição padrão:

Além de vários tipos de números inteiros não assinados, ele também fornece o número inteiro de 1 byte que você está procurando:

int1 (signed 8-bit integer)
uint1 (unsigned 8-bit integer)
uint2 (unsigned 16-bit integer)
uint4 (unsigned 32-bit integer)
uint8 (unsigned 64-bit integer)

Leia o capítulo "Discussão" no site vinculado, explicando possíveis complicações. Você precisa ter cuidado com conversões de tipo e literais numéricos ao introduzir mais tipos de número inteiro ...

Gambiarra

Uma solução possível e simples seria codificar valores inteiros de 1 byte como "char"um tipo simplista "interno" de 1 caractere, que realmente usa um único byte de armazenamento , valores de byte de um inteiro assinado de 1 byte, a metade superior representada como Caracteres ASCII.

Você pode codificar valores no intervalo de -128 a 127 . Demo:

SELECT i
     , i::"char"
     , i::"char"::int
FROM   generate_series(-128,127) i;

Existem vários caracteres não destinados à exibição. Portanto, codifique antes de armazenar e decodifique antes de exibir ...

Lembre-se: "char"é um tipo "interno" destinado a enumeração simples e barata. Não foi oficialmente projetado para o que estamos fazendo aqui e não é portátil para outros RDBMS. Não há garantias pelo projeto Postgres para isso.

Minhas sugestões iniciais foram descuidadamente baseadas na suposição de que cobriríamos o intervalo de um número inteiro de 1 byte não assinado (0-255) e poderíamos usá-lo textcomo trampolim. Evan apontou os erros do meu caminho: isso só funciona para os números 1 a 127 e falha no resto. Em vez disso, use o intervalo inteiro -128 a 127 e faça a conversão entre "char"e integerdiretamente para corrigir os dois problemas.

Erwin Brandstetter
fonte