_"char"
_について話している人がよくいます。使ったことがない。それはドキュメントで次のように定義されています:
タイプ「char」(引用符に注意)は、1バイトのストレージしか使用しないという点でchar(1)とは異なります。これは、単純な列挙型としてシステムカタログで内部的に使用されます。
そしてさらに、
_"char" 1 byte single-byte internal type
_
それで、それが1バイトである場合、ドメインは何で、どのようにそれを利用しますか?署名されていますか、署名されていませんか? @ Erwin Brandstetterによるこの投稿では、彼はそれをレイアウトしています が、私はまだ混乱しています。彼はascii()
とchr()
を使用しており、これを提供しています
_SELECT i
, chr(i)::"char" AS i_encoded
, ascii(chr(i)::"char") AS i_decoded
FROM generate_series(1,256) i;
_
それは10から11の間で本当に奇妙なことをしています。
_ i | i_encoded | i_decoded
-----+-----------+-----------
...
8 | \x08 | 8
9 | | 9
10 | +| 10
| | -- WTF is going on here.
11 | \x0B | 11
12 | \x0C | 12
...
_
ここでも本当に奇妙です:
_ 126 | ~ | 126
127 | \x7F | 127
128 | | 128
129 | | 128
130 | | 128
131 | | 128
_
128の北にあるものすべてが128としてデコードされるのはなぜですか?しかし、bizzareを少し上げるために、192の後にスイッチがあり、それらは192としてデコードされます。
_ 190 | | 128
191 | | 128
192 | | 192
193 | | 192
194 | | 192
195 | | 192
196 | | 192
197 | | 192
_
アーウィンさんのコメント
表示用ではない文字がいくつかあります。したがって、保存する前にエンコードし、表示する前にデコードします...
なぜそれをエンコードする必要があるのかよくわかりません
_CREATE TABLE foo AS
SELECT i::"char"
FROM generate_series(-128,127) i;
_
それはうまくいきます。 intを使用して戻すことができます
_SELECT i::int FROM foo;
_
要するに、
Erwinがと言ったときに0を格納できないようにするにはどうすればよいですか(0 =は許可されていません)
_CREATE TABLE foo AS SELECT 0::int::"char" AS x;
SELECT x::int FROM foo;
x
---
0
_
chr(10)
... [〜#〜] linefeed [〜#〜] 文字(別名エスケープシーケンス\n
)を生成し、psqlは文字を改行付きで表示します(+
で示されます)。すべてが正しい。
ascii()
は128または192を生成しますか?それは私が犯した間違いから始まります。 参照された回答 (現在修正済み)のunsigned1バイト整数(0から255)の範囲を"char"
がカバーすることを不注意に仮定しました、しかし、実際には内部的にsigned1バイト整数(-128から127)の範囲です。
ascii()
はtext
パラメータを取り、"char"
からtext
への暗黙のキャストはマルチバイトエンコードされた文字をUnicodeで生成し、関数は( ascii()
):
引数の最初の文字のASCIIコード。 UTF8の場合、文字のUnicodeコードポイントを返します。他のマルチバイトエンコーディングの場合、引数はASCII文字でなければなりません。
したがって、多くの切り捨てられた値を取得します。 128と192は、マルチバイト文字の先頭バイトのバイト値です。
Nullバイトを格納できないことは、"char"
ではなく、通常の文字タイプ(text
、char
、varchar
)にのみ影響します。私はバギーの例に当てはまります。私はtext
に飛び石としてキャストしているからです。 "char"
とinteger
の間で直接キャストする場合、制限は適用されません。 chr()
: のマニュアル
テキストデータタイプはそのようなバイトを格納できないため、NULL(0)文字は使用できません。
「char」の場合はそうではありません。ここで、0
は空の文字列''
にマップされます。
SELECT ''::"char"::int -- 0
, 0::"char" = ''; -- t
注意:"char"
は、単純で安価な列挙を目的とした「内部」型です。ここでの作業用に公式に設計されたものではなく、他のRDBMSに移植することもできません。これに対するPostgresプロジェクトによる保証はありません。
符号付き範囲へのシフトを行うために、支援に役立ついくつかの関数を作成できます。このリストは、関数notキャストを作成して、このプロセスで符号なし1バイト整数範囲_[0-255]
_から文字が_[-128,127]
_に必要な符号付き1バイト範囲。
pguint
は、タイプ_uint1
_を提供します。これは、1バイトの符号なし整数としてストレージを提供します。 拡張機能をコンパイルおよびインストールできる場合は、 。pg_uchar
_ を使用しています。そのリポジトリで_install.sql
_ファイルを見つけることができます。READMEからの抜粋
これで、たとえば、テーブルで_[0-255]
_の範囲の値を格納できます。
_CREATE TABLE t(x) AS VALUES
(to_uchar(255)),
(to_uchar(0));
_
それらをbit(8)
に変換します
_SELECT to_bit8(x) FROM t;
to_bit8
----------
11111111
00000000
(2 rows)
_
おそらく、下位2ビットをクリアしたい場合は、BITWISE-ANDを使用して実行できます。
_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)
_