在文本转换中丢失空间

时间:2016-03-07 18:40:49

标签: postgresql

这个直觉期望“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指南在哪里(它需要一个红色警报)说明了什么?

1 个答案:

答案 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)通常是最慢的   三,因为它额外的存储成本和较慢的分拣。在   大多数情况下应使用文字或字符变化。