Je vois souvent des gens parler de "char"
. Je ne l'ai jamais utilisé. Il est défini dans les docs comme étant,
Le type "Char" (notez les devis) est différent du char (1) en ce qu'il utilise qu'un octet de stockage. Il est utilisé intérieurement dans les catalogues système comme type de dénombrement simpliste.
Et plus loin,
"char" 1 byte single-byte internal type
Donc, si c'est un octet, quel est le domaine et comment en feriez-vous l'utiliser? Est-ce signé ou non signé? Dans ce post par @ @ erwin Brandsetter, il la pose , mais je suis toujours confus. Il utilise ascii()
et chr()
, et fournit ceci
SELECT i
, chr(i)::"char" AS i_encoded
, ascii(chr(i)::"char") AS i_decoded
FROM generate_series(1,256) i;
Cela fait quelque chose de vraiment bizarre entre 10 et 11.
i | i_encoded | i_decoded
-----+-----------+-----------
...
8 | \x08 | 8
9 | | 9
10 | +| 10
| | -- WTF is going on here.
11 | \x0B | 11
12 | \x0C | 12
...
Il devient aussi vraiment bizarre ici:
126 | ~ | 126
127 | \x7F | 127
128 | | 128
129 | | 128
130 | | 128
131 | | 128
Pourquoi tout est-il au nord de 128 étant décodé comme 128? Mais pour prendre un peu le Bizzare, après 192, il y a un commutateur et ils sont décodés comme 192 ..
190 | | 128
191 | | 128
192 | | 192
193 | | 192
194 | | 192
195 | | 192
196 | | 192
197 | | 192
Erwin dit
Plusieurs caractères ne sont pas destinés à l'affichage. Alors encoder avant de stocker et de décoder avant d'afficher ...
Je ne suis pas sûr de savoir pourquoi nous devrions-nous encoder du tout si nous faisons exactement ce que ces questions posent
CREATE TABLE foo AS
SELECT i::"char"
FROM generate_series(-128,127) i;
Cela fonctionne bien. Nous pouvons obtenir l'intégralité de l'intégralité en utilisant
SELECT i::int FROM foo;
Donc en bref,
Comment puis-je déclencher l'incapacité à stocker 0, lorsque erwin dit , vous ne pouvez pas encoder 0 de cette façon (caractère null non autorisé)
CREATE TABLE foo AS SELECT 0::int::"char" AS x;
SELECT x::int FROM foo;
x
---
0
chr(10)
... produise le [~ # ~] lignesfeed [~ # ~]] caractère (AKA Séquence d'échappée \n
) et PSQL affiche le caractère avec une nouvelle ligne (indiquée par +
). Tout correct là-bas.
ascii()
produit 128 ou 192?Cela commence par une erreur que j'ai faite. Je suppose négligemment "char"
Couvrirait la plage d'un non signé entier de 1 octet (0 à 255) dans le référencé Réponse (maintenant fixe), mais c'est en fait la plage de signée entier de 1 octet (-128 à 127) en interne.
ascii()
prend un paramètre text
, la coute implicite de "char"
à text
génère un caractère codé multibyte dans Unicode et la fonction renvoie (- par documentation sur ascii()
):
Code ASCII du premier caractère de l'argument. Pour UTF8, renvoie le point de code Unicode du personnage. Pour d'autres codages multibytes, l'argument doit être un ASCII caractère.
Nous obtenons donc beaucoup de valeurs tronquées. 128 et 192 sont des valeurs d'octet pour l'octet de premier plan des caractères multibytes.
L'incapacité de stocker NULL octets n'affecte que les types de caractères réguliers (text
, char
, varchar
), pas "char"
. Cela s'applique à mon exemple de buggy, car je mets à text
comme pierre de descente. Tout en casissant entre "char"
Et integer
directement, la limitation ne s'applique pas. le manuel sur chr()
:
Le caractère NULL (0) n'est pas autorisé car les types de données de texte ne peuvent pas stocker de tels octets.
Pas ainsi pour "Char", où 0
Est mappé sur la chaîne vide ''
:
SELECT ''::"char"::int -- 0
, 0::"char" = ''; -- t
N'oubliez pas: "char"
Est toujours un type "interne" destiné à une énumération simple et bon marché. Pas officiellement conçu pour ce que nous faisons ici, et non portable à d'autres SGBDM. Il n'y a pas de garantie par le projet Postgres pour cela.
Pour effectuer le déplacement vers la plage signée, vous pouvez créer des fonctions pour aider à aider. Cette liste créera des fonctions pas jette pour aider à aider à ce processus d'aller de une plage d'un octet non signé de [0-255]
à un a signé une plage d'octets que le caractère nécessite [-128,127]
.
pguint
fournit un type uint1
Qui permet de stocker en tant que stockage en tant qu'int d'un octet-non signé. Si vous êtes capable de compiler et d'installer des extensions à prendre en compte. ce.pg_uchar
. Vous pouvez trouver le fichier install.sql
Dans ce référentiel.Un extrait du Readme
Maintenant, vous pouvez faire par exemple stocker les valeurs dans la plage de [0-255]
sur la table.
CREATE TABLE t(x) AS VALUES
(to_uchar(255)),
(to_uchar(0));
Convertissez-les en bit(8)
SELECT to_bit8(x) FROM t;
to_bit8
----------
11111111
00000000
(2 rows)
Peut-être que vous voulez effacer les deux bits d'ordre inférieur, vous pouvez le faire avec le bitwise-et,
UPDATE t
SET x = to_uchar( to_bit8(x) & (x'fc')::bit(8) );
SELECT to_bit8(x) FROM t;
to_bit8
----------
11111100
00000000
(2 rows)