Comment stocker un entier d'un octet dans PostgreSQL?

14

Dans la documentation PostgreSQL, il est dit que les types de données entiers peuvent être stockés dans un espace de deux, quatre ou huit octets. L'une des colonnes d'une table dans ma base de données contient une valeur entière sur un octet et je souhaite qu'elle soit stockée dans un type de données sur un octet.

  1. Existe-t-il une extension ou un moyen d'utiliser le type de données entier à un octet dans PostgreSQL?
  2. Combien d'octets est NUMERIC (1,0)?
ukll
la source

Réponses:

16

Non , il n'y a pas d'entier de 1 octet dans la distribution standard de Postgres. Tous les types numériques intégrés de PostgreSQL standard occupent 2 octets ou plus.

Extension pguint

Mais oui , il y a l' extension pguint , maintenue par Peter Eisentraut, l'un des principaux développeurs de Postgres. Cela ne fait pas partie de la distribution standard:

En plus de divers types d'entiers non signés, il fournit également l'entier de 1 octet que vous recherchez:

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)

Assurez-vous de lire le chapitre "Discussion" sur le site lié, expliquant les complications possibles. Vous devez être prudent avec les transformations de type et les littéraux numériques lors de l'introduction de types plus entiers ...

solution de contournement

Une solution de contournement simple et possible consisterait à coder des valeurs entières sur 1 octet comme "char"un type simplifié "interne" à 1 caractère, qui utilise en fait un seul octet de stockage , des valeurs en octets d'un entier signé sur 1 octet, la moitié supérieure représentée comme Caractères ASCII.

Vous pouvez encoder des valeurs comprises entre -128 et 127 . Démo:

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

Plusieurs caractères ne sont pas destinés à être affichés. Donc, encodez avant de stocker et de décoder avant d'afficher ...

N'oubliez pas: "char"est un type "interne" destiné à une énumération simple et bon marché. Pas officiellement conçu pour ce que nous faisons ici, et non portable sur d'autres SGBDR. Il n'y a aucune garantie par le projet Postgres pour cela.

Mes suggestions initiales étaient négligemment basées sur l'hypothèse que nous couvririons la plage d'un entier non signé de 1 octet (0-255) et que nous pourrions l'utiliser textcomme tremplin. Evan a souligné les erreurs de mon chemin: cela ne fonctionne que pour les numéros 1 - 127 et échoue pour le reste. À la place, utilisez la plage entière -128 à 127 et effectuez une conversion entre "char"et integerdirectement pour résoudre les deux problèmes.

Erwin Brandstetter
la source