代码之家  ›  专栏  ›  技术社区  ›  Tim unnamed eng

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

  •  2
  • Tim unnamed eng  · 技术社区  · 6 年前

    从数据库系统概念

    比较char类型的两个值时, 如果它们的长度不同,则会自动将额外的空间添加到较短的空间 在比较之前,把它们做成相同的尺寸。

    比较char类型和varchar类型时 ,可能需要在varchar类型中添加额外的空格以使长度 相等,在比较之前;然而,这可能或不可能做到, 取决于数据库系统。因此,即使相同的值 avi存储在上面的属性a和b中,比较a=b可以 返回错误。

    我们一直推荐你 使用varchar类型而不是char 键入以避免这些问题。

    你能举例说明比较char类型的两个值和比较varchar类型的两个值吗?比较中使用的运算符是什么, = ?

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

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

    谢谢。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Schwern    6 年前

    基本问题是 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>
    

    但MySQL不会,除非 PAD_CHAR_TO_FULL_LENGTH 被设置。

    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, 并以这种方式存储和显示 .

    …在比较类型character的两个值时,尾随空格被视为语义无关紧要的空格,并且被忽略。在空白显著的排序规则中,此行为可能会产生意外的结果;例如 SELECT 'a '::CHAR(2) collate "C" < E'a\n'::CHAR(2) 返回true,即使C语言环境将空格视为大于换行符

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

    存储引擎已经改进到几乎没有理由使用 烧焦 不再。

    这三种类型之间没有性能差异,除了使用空白填充类型时增加存储空间,以及在存储到长度受限列中时,检查CPU长度的一些额外CPU周期。虽然character(n)在其他一些数据库系统中具有性能优势,但是postgresql中没有这样的优势; 事实上,字符(n)通常是这三个字符中最慢的一个,因为它有额外的存储成本。 在大多数情况下,应使用不同的文本或字符。

    其中一例 烧焦 可以 被证明是存储非常小,固定大小的字符串。例如, ISO 2 character country codes 可能存储为 char(2) . 但在如此小的字符串上,不太可能注意到性能差异。

    烧焦 头痛是最好避免的。