Eva*_*oll 9 postgresql datatypes storage cast
我经常看到人们谈论"char"
。我从来没有用过它。它在文档中定义为,
“char”类型(注意引号)与 char(1) 的不同之处在于它只使用一个字节的存储空间。它在系统目录中作为一种简单的枚举类型在内部使用。
并进一步,
"char" 1 byte single-byte internal type
Run Code Online (Sandbox Code Playgroud)
那么,如果它是一个字节,那么域是什么,您将如何使用它?它是签名的还是未签名的?在@Erwin Brandstetter 的这篇文章中,他对此进行了阐述,但我仍然感到困惑。他正在使用ascii()
and chr()
,并提供了这个
SELECT i
, chr(i)::"char" AS i_encoded
, ascii(chr(i)::"char") AS i_decoded
FROM generate_series(1,256) i;
Run Code Online (Sandbox Code Playgroud)
这在 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
...
Run Code Online (Sandbox Code Playgroud)
这里也变得非常奇怪:
126 | ~ | 126
127 | \x7F | 127
128 | | 128
129 | | 128
130 | | 128
131 | | 128
Run Code Online (Sandbox Code Playgroud)
为什么 128 以北的所有内容都被解码为 128?但是为了让大家感到奇怪,在 192 之后有一个开关,它们被解码为 192 ..
190 | | 128
191 | | 128
192 | | 192
193 | | 192
194 | | 192
195 | | 192
196 | | 192
197 | | 192
Run Code Online (Sandbox Code Playgroud)
欧文 说
有几个字符不适合显示。因此,在存储之前进行编码并在显示之前进行解码......
我不知道为什么我们应该编码,尽管如果我们完全按照问题的要求去做
CREATE TABLE foo AS
SELECT i::"char"
FROM generate_series(-128,127) i;
Run Code Online (Sandbox Code Playgroud)
这很好用。我们可以使用
SELECT i::int FROM foo;
Run Code Online (Sandbox Code Playgroud)
所以简而言之,
当 Erwin 说您不能以这种方式编码 0时,我如何触发无法存储 0 (不允许使用空字符)
CREATE TABLE foo AS SELECT 0::int::"char" AS x;
SELECT x::int FROM foo;
x
---
0
Run Code Online (Sandbox Code Playgroud)Erw*_*ter 11
chr(10)
... 产生LINEFEED字符(又名转义序列\n
)并且 psql 显示带有换行符的字符(由 表示+
)。那里一切都正确。
ascii()
产生 128 或 192?它始于我犯的一个错误。我粗心地认为"char"
会涵盖一个范围在引用的答案(现已修复)中无符号1 字节整数(0 到 255)的范围,但它实际上是内部有符号1 字节整数(-128 到 127)的范围。
ascii()
接受一个text
参数,隐式转换来自"char"
to转换text
产生一个多字节编码的 unicode 字符,并且该函数返回(根据 上的文档ascii()
):
参数第一个字符的 ASCII 码。对于 UTF8,返回字符的 Unicode 代码点。对于其他多字节编码,参数必须是 ASCII 字符。
所以我们得到了很多截断的值。128 和 192 是多字节字符的前导字节的字节值。
无法存储空字节仅影响常规字符类型(text
, char
, varchar
),而不影响"char"
. 它适用于我的越野车示例,因为我将其text
作为垫脚石。在之间"char"
和integer
直接进行转换时,限制不适用。手册chr()
:
不允许使用 NULL (0) 字符,因为文本数据类型无法存储此类字节。
“char”不是这样,其中0
映射到空字符串''
:
SELECT ''::"char"::int -- 0
, 0::"char" = ''; -- t
Run Code Online (Sandbox Code Playgroud)
请记住:"char"
仍然是一个“内部”类型,用于简单和廉价的枚举。不是为我们在这里所做的事情而正式设计的,并且不能移植到其他 RDBMS。Postgres 项目对此没有任何保证。