这个直觉期望“foo bar”的例子显示了奇怪的行为:
SELECT 'foo'|| '#'::char ||'bar' -- char ok, foo#bar
SELECT 'foo'|| '#' ||'bar' -- literal ok
SELECT 'foo'|| '#'::text ||'bar' -- text ok
SELECT 'foo'|| ' '::char ||'bar' -- STRANGE! LOSTING SPACE!
SELECT ('foo'|| ' '::char ||'bar')='foobar' -- yes, it is true... strange
SELECT 'foo'|| ' '::text ||'bar' -- text OK
SELECT 'foo'|| (' '::char)::text ||'bar' -- char-to-text lost!
SELECT 'foo'|| ' ' ||'bar' -- literal OK
为什么PostgreSQL会这样做?它不直观,而且似乎容易出错。
PS:PostgreSQL指南在哪里(它需要一个红色警报)说明了什么?
答案 0 :(得分:4)
这是经常建议坚持使用varchar()
或Postgres text
类型的众多原因之一。
SQL标准要求用空格填充CHAR()值以填充剩余的字节。例如:
'A'::CHAR(5)
将导致存储"A "
。现在,如果有另一个不同长度但相同内容的字段:
'A'::CHAR10 = 'A'::CHAR(5)
我们希望这样说TRUE
,对吗?因此,必须修剪为填充CHAR()
添加填充的空格。
这不是一个Postgres问题,而是一个磁盘存储或sql标准问题。必须将某些内容写入磁盘上的那些字节,space
是标准的。有些数据库仅用于比较或转换,而其他数据库,如Postgres,几乎可以修剪任何功能。
由于您要将空格转换为CHAR(1)
(1是未指定的默认长度,尽管对于此问题并不重要),您的空间会因填充而丢失。这只是使用CHAR()
的一个警告。如果你这样做,那真是太该死了,如果你没有这种情况该死的。
而是将该内容转换为VARCHAR()
或TEXT
,因为它们几乎总是优于CHAR()
的类型。
在Postgresql文档中注意到:
提示:除此之外,这三种类型之间没有性能差异 使用空白填充类型时增加的存储空间,和 存储到a时,检查长度的额外CPU周期很少 长度受限的列。虽然字符(n)具有性能 在其他一些数据库系统中的优势,没有这样的优势 在PostgreSQL中;事实上,字符(n)通常是最慢的 三,因为它额外的存储成本和较慢的分拣。在 大多数情况下应使用文字或字符变化。