在 PostgreSQL 中,character(n) 基本上只是 varchar,在输入/输出上有空格填充。这很笨拙,应该避免。它消耗与填充到最大长度的varchar 或text 字段相同的存储空间(见下文)。 char(n) 是一个历史缺陷,应该避免 - 至少在 PostgreSQL 中它没有任何优势,并且与 left(...) 之类的东西有一些奇怪的怪癖。
varchar(n)、varchar 和 text 都使用相同的存储空间 - 您提供的不带填充的字符串的长度。它仅使用字符实际所需的存储空间,而与长度限制无关。此外,如果字符串为空,PostgreSQL 根本不会为它存储值(甚至没有长度标头),它只是在记录的空位图中设置空位。
合格的varchar(n) 与不合格的varchar 基本相同,但check 约束length(colname) < n。
尽管其他一些 cmets/answers 在说什么,char(n)、varchar、varchar(n) 和 text 都是 TOASTable 类型。它们都可以离线存储和/或压缩。控制存储使用ALTER TABLE ... ALTER COLUMN ... SET STORAGE。
如果您不知道需要的最大长度,只需使用text 或不合格的varchar。没有空间损失。
有关更多详细信息,请参阅the documentation on character data types,有关它们如何存储的一些内部信息,请参阅database physical storage,尤其是TOAST。
演示:
CREATE TABLE somechars(c10 char(10), vc10 varchar(10), vc varchar, t text);
insert into somechars(c10) values (' abcdef ');
insert into somechars(vc10) values (' abcdef ');
insert into somechars(vc) values (' abcdef ');
insert into somechars(t) values (' abcdef ');
每个列的查询输出:
SELECT 'c10', pg_column_size(c10), octet_length(c10), length(c10)
from somechars where c10 is not null;
是:
?column? | pg_column_size | octet_length | length
c10 | 11 | 10 | 8
vc10 | 10 | 9 | 9
vc | 10 | 9 | 9
t | 10 | 9 | 9
pg_column_size 是字段中数据的磁盘大小。 octet_length 是没有标题的未压缩大小。 length 是“逻辑”字符串长度。
如您所见,char 字段已填充。它浪费了空间,而且它也给length 提供了一个非常令人惊讶的结果,因为输入是 9 个字符,而不是 8 个字符。那是因为 Pg 无法区分你自己输入的前导空格和前导空格之间的区别添加为填充。
所以,不要使用char(n)。
顺便说一句,如果我正在设计一个数据库,我从不使用varchar(n) 或char(n)。我只是使用 text 类型并添加适当的 check 约束,如果有值的应用程序要求。我认为varchar(n) 在标准中有点小瑕疵,但我认为它对于具有磁盘布局且大小限制可能会影响存储的数据库很有用。