使用varchar类型而不是char类型可以避免哪些比较问题?

时间:2018-07-25 23:24:20

标签: sql postgresql

来自数据库系统概念

  

比较两个char类型的值时,如果它们的长度不同,多余的空格会自动添加到较短的   在比较之前,使它们的大小相同。

     

在将char类型与varchar类型进行比较时,可能希望将额外的空格添加到varchar类型中以形成长度   相等,比较之前;但是,这可能会或可能不会完成,   取决于数据库系统。结果,即使值相同   “ Avi”存储在上面的属性A和B中,可以比较A = B   返回false。

     

我们建议您始终使用varchar类型而不是char   键入以避免出现这些问题。

您能否举一些例子来说明比较char类型的两个值,以及比较varchar类型的两个值?比较中=使用了哪些运算符?

使用varchar类型而不是char类型可以避免哪些问题?为什么?

这通常是关于SQL的,我想它也可能适用于PostgreSQL,因为它与SQL标准很好地兼容。

谢谢。

1 个答案:

答案 0 :(得分:3)

基本问题是char将用空格填充值,这可能会导致一些令人惊讶且不一致的结果。

在这里我们看到Postgres保留了尾随空格。

test=> create table foo ( c char(10), v varchar(10) );
CREATE TABLE

test=> insert into foo values ('foo', 'foo');
INSERT 0 1

test=> select * from foo;
     c      |  v  
------------+-----
 foo        | foo

test=> select concat(c, '>'), concat(v, '>') from foo where c = 'foo     ';
   concat    | concat 
-------------+--------
 foo       > | foo>

但是,除非设置PAD_CHAR_TO_FULL_LENGTH,否则MySQL不会。

mysql> create table foo ( c char(10), v varchar(10) );

mysql> insert into foo values ('foo', 'foo');

mysql> select * from foo;
+------+------+
| c    | v    |
+------+------+
| foo  | foo  |
+------+------+

mysql> select concat(c, '>'), concat(v, '>') from foo where c = 'foo     ';
+----------------+----------------+
| concat(c, '>') | concat(v, '>') |
+----------------+----------------+
| foo>           | foo>           |
+----------------+----------------+

mysql> set sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';

mysql> select concat(c, '>'), concat(v, '>') from foo where c = 'foo     ';
+----------------+----------------+
| concat(c, '>') | concat(v, '>') |
+----------------+----------------+
| foo       >    | foo>           |
+----------------+----------------+

The PostgreSQL documentation概述了几个问题。

  

字符类型的值在物理上用空格填充到指定宽度n, ,并以这种方式存储和显示

     

...当比较两个字符类型的值时,尾随空格在语义上是微不足道的,并且被忽略。在空白很重要的排序规则中,此行为可能会产生意外的结果。例如SELECT 'a '::CHAR(2) collate "C" < E'a\n'::CHAR(2)返回true,即使C语言环境会认为空格大于换行符

     

将字符值转换为其他字符串类型之一时,将删除尾随空格。

存储引擎已得到改进,因此几乎没有理由再使用char

  

这三种类型之间没有性能差异,除了使用空白填充类型时增加的存储空间,以及在存储到受长度限制的列中时需要一些额外的CPU周期来检查长度。尽管character(n)在某些其他数据库系统中具有性能优势,但在PostgreSQL中却没有这种优势。实际上, 字符(n)通常是三个字符中最慢的一个,因为它会增加存储成本。 在大多数情况下,应改用文本或字符变化。

char 可能是合理的一种情况是存储非常小的固定大小的字符串。例如,ISO 2 character country codes可能存储为char(2)。但是在这么小的字符串上,性能差异不太可能被注意到。

char最好避免头痛。