Postgresql

一字節“char”類型在 PostgreSQL 中究竟是如何工作的?

  • December 5, 2018

我經常看到人們談論"char"。我從來沒有使用過它。它在文件中定義為,

“char” 類型(注意引號)與 char(1) 的不同之處在於它只使用一個字節的儲存空間。它在系統目錄內部用作簡單的列舉類型。

並進一步,

"char"  1 byte  single-byte internal type

那麼,如果它是一個字節,那麼域是什麼,你將如何使用它?它是簽名的還是未簽名的?在@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;

這在 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?但是為了稍微提高一點,在 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;

這很好用。我們可以使用

SELECT i::int FROM foo;

所以簡而言之,

  1. Erwin 的程式碼在 i 變為空的 10-11 之間做什麼?
  2. 為什麼128重複了這麼多次?
  3. 為什麼192重複了這麼多次?
  4. 當 Erwin 說你不能以這種方式編碼 0 時,我如何觸發無法儲存 0 (不允許空字元)
CREATE TABLE foo AS SELECT 0::int::"char" AS x;
SELECT x::int FROM foo;
x 
---
0

1.chr(10)

… 生成LINEFEED字元(又名轉義序列\n)並且 psql 顯示帶有換行符的字元(由 表示+)。那裡一切都正確。

2. & 3.ascii()產生 128 還是 192?

從我犯的一個錯誤開始。我不小心假設在引用的答案"char"(現已修復)中涵蓋了無符號1 字節整數(0 到 255)的範圍,但它實際上是內部有符號1 字節整數(-128 到 127)的範圍。

ascii()接受一個text參數,隱式轉換 from "char"totext在 unicode 中產生一個多字節編碼的字元,並且函式返回(根據文件ascii()):

參數的第一個字元的 ASCII 碼。對於 UTF8,返回字元的 Unicode 程式碼點。對於其他多字節編碼,參數必須是 ASCII 字元。

所以我們得到了很多截斷的值。128 和 192 是多字節字元的前導字節的字節值。

4.空字節

無法儲存空字節僅影響正常字元類型(text, char, varchar),而不影響"char"。它適用於我的越野車範例,因為我將其text作為墊腳石。在直接之間"char"進行轉換integer時,該限制不適用。手冊chr()

不允許使用 NULL (0) 字元,因為文本數據類型無法儲存此類字節。

“char”不是這樣,其中0映射到空字元串''

SELECT ''::"char"::int  -- 0
    , 0::"char" = '';  -- t

請記住:"char"仍然是一種“內部”類型,用於簡單而廉價的列舉。不是為我們在這裡所做的事情而正式設計的,也不能移植到其他 RDBMS。Postgres 項目對此沒有任何保證。

引用自:https://dba.stackexchange.com/questions/166155