web-dev-qa-db-fra.com

Comment stocker un entier d'un octet dans PostgreSQL?

Dans la documentation PostgreSQL, il est dit que types de données entiers peut être stocké 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)?
14
ukll

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

Extension pguint

Mais oui , il y a le extension pguint =, maintenu 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 faire preuve de prudence avec les transformations de type et les littéraux numériques lorsque vous introduisez plus de types entiers ...

Workaround

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

Vous pouvez encoder des valeurs dans la plage de - 128 à 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 encoder avant de stocker et décoder avant d'afficher ...

Rappelles toi: "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 utiliser text comme 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 integer directement pour résoudre les deux problèmes.

16
Erwin Brandstetter