zoukankan      html  css  js  c++  java
  • MYSQL中 char 和 varchar

    CHAR和VARCHAR类型相似,差别主要在存储,尾随空格和检索方式上。

    CHAR和VARCHAR相同的是:CHAR和VARCHAR都指定了字符长度,注意是字符长度。例如char(30) 和 varchar(30)表示都可以存30个字符。有一点要注意的是在utf8mb4编码中,每个字符占4个节点。在utf8中,每个字符占3个字节。当要存储的字符超过CHAR/VARCHAR指定的最大长度。在sql mode 没开启的时候是截断要存储的字串,只存储前30位

    CHAR列中的值是定长的字符串。长度可以指定为0到255个字符(例如utf8mb4: 0-255*4个字节)之间的值当使用CHAR存储字符时,以CHAR(30)为例,不够30个字符的以空格向右填充。当检索CHAR值时,除非启用sqlmode:PAD_CHAR_TO_FULL-LENGTH SQL模式,否则将删除尾部空格。

    VARCHAR列中的值是可变长度的字符串。长度可以指定为0到65535字节之间的值。VARCHAR的有效最大长度取决于最大行大小(65535字节,在所有列之间共享)和使用的字符集

    与CHAR不同的是,VARCHAR在存储数据的时候,会额外存储存储1-2个字节(例如varchar(4),这1-2个字节长度不会算在这4个字符长度里面,不用担心被截断),这1-2个字节用来记录数据字符的长度。假如数据字符长度小于等于255,则使用1个字节记录数据长度。大于则用两个字节。CHAR只存储数据本身。如下图所示。

    (误区:varchar在查询时比char慢是因为会计算varchar的字节长度(X))

    在latin1编码中,Latin1不能存中文。英文字母为1个字节。

    ValueCHAR(4)Storage RequiredVARCHAR(4)Storage Required
    '' '    ' 4 bytes '' 1 byte
    'ab' 'ab  ' 4 bytes 'ab' 3 bytes
    'abcd' 'abcd' 4 bytes 'abcd' 5 bytes
    'abcdefgh' 'abcd' 4 bytes 'abcd' 5 bytes

    需要注意的是VARCHAR值在存储时不填充空格。在存储和检索值时,尾部空格将被保留,这与标准SQL一致。而CHAR则相反,CHAR在储存时会填充空格,在检索时尾部空格会去掉,无论这个尾部空格是自动填充的还是数据本身的。举个例子:

    mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> INSERT INTO vc VALUES ('ab  ', 'ab  ');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;
    +---------------------+---------------------+
    | CONCAT('(', v, ')') | CONCAT('(', c, ')') |
    +---------------------+---------------------+
    | (ab  )              | (ab)                |
    +---------------------+---------------------+
    1 row in set (0.06 sec)


     

    做三个实验。

    mysql> show create table vc;
    +-------+------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                         |
    +-------+------------------------------------------------------------------------------------------------------------------------------------------------------+
    | vc    | CREATE TABLE `vc` (
      `v` varchar(4) DEFAULT NULL,
      `c` char(4) DEFAULT NULL,
      UNIQUE KEY `v_UNIQUE` (`v`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
    +-------+------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    

      

    1.查询语句 where 字段='       ab';

    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vc where v='               ab';
    Empty set (0.00 sec)
    
    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vc where c='                 ab';
    Empty set (0.00 sec)
    

     

    2.查询语句 where 字段='ab                 ';

    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vc where v='ab               ';
    +--------------------+--------------------+
    | concat('(',v, ')') | concat('(',c, ')') |
    +--------------------+--------------------+
    | (ab )              | (ab)               |
    +--------------------+--------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vc where c='ab               ';
    +--------------------+--------------------+
    | concat('(',v, ')') | concat('(',c, ')') |
    +--------------------+--------------------+
    | (ab )              | (ab)               |
    +--------------------+--------------------+
    1 row in set (0.00 sec)


    在所有字符串的比较中,不论是varchar,text,char 都会忽略去掉尾部空格,除了like子句,like子句不会去掉尾部空格如下所示

      

    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vipshop_dba.vc where c like 'ab'; (无尾部空格)
    +--------------------+--------------------+
    | concat('(',v, ')') | concat('(',c, ')') |
    +--------------------+--------------------+
    | (ab ) | (ab) |
    | ( ab ) | (ab) |
    +--------------------+--------------------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vipshop_dba.vc where c like 'ab '; (有尾部空格)
    Empty set (0.00 sec)
    
     
    
    CHAR在储存时会填充空格,在检索时尾部空格会去掉,无论这个尾部空格是自动填充的还是数据本身的。这个去掉尾部空格的动作在比较之前会发生
    
     
    
    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vipshop_dba.vc where v like 'ab ';   (有尾部空格)
    +--------------------+--------------------+
    | concat('(',v, ')') | concat('(',c, ')') |
    +--------------------+--------------------+
    | (ab ) | (ab) |
    +--------------------+--------------------+
    1 row in set (0.01 sec)
    
    mysql> SELECT concat('(',v, ')'),concat('(',c, ')') FROM vipshop_dba.vc where v like 'ab';   (无尾部空格)
    Empty set (0.00 sec)
    

      

    3.varchar 设置unique 索引 观察  'ab' 和 'ab      '是否同时能存在

    mysql> insert into vc (v,c)values('ab     ', 'ab        ')
        -> ;
    ERROR 1062 (23000): Duplicate entry 'ab  ' for key 'v_UNIQUE'
    mysql> insert into vc (v,c)values(' ab     ', 'ab        ')
        -> ;
    Query OK, 1 row affected, 1 warning (0.00 sec)
    说明虽然varchar 尾部空格可以保留,但是索引上似乎额外做了限制。如果varchar是唯一索引,插入的值区别只在于尾部空格的数量的话则会报 Duplicate key

      

    说到字节限制这个问题,也想提醒一下。索引长度也是有限制的噢:

    innodb引擎的每个索引列长度限制为767字节(bytes),所有组成索引列的长度和不能大于3072字节。注意是字节,varchar(256)在不同的编码字节计算不同。例如在utf8mb4中,一个字符占4个字节,256个字符=1024个字节。就达不到索引覆盖的效果噢。相当于只做了一个前缀索引(非常重要,前缀索引是需要回(主键)表的,二次查询)

    innodb引擎可以通过配置innodb_large_prefix=on(全局参数,动态生效)来让单个索引列长度限制上升到3072字节

    • 在MySQL5.7里默认 innodb_large_prefix=1 解除了767bytes长度限制,但是单列索引长度最大还是不能超过3072bytes
    • 在MySQL5.6里默认 innodb_large_prefix=0 限制单列索引长度不能超过767bytes。需要设置innodb_large_prefix=ON、innodb_file_format=barracuda、innodb_file_per_table=ON ,且Innodb表的存储格式为 DYNAMIC 或 COMPRESSED,则前缀索引最多可包含3072个字节
  • 相关阅读:
    查看端口有没有被占用
    微信公众号2()
    How to insert a segment of noise to music file
    puppet practice
    Docker Commands
    LempelZiv algorithm realization
    The algorithm of entropy realization
    Java network programmingguessing game
    Deploy Openstack with RDO and Change VNC console to Spice
    puppet overview
  • 原文地址:https://www.cnblogs.com/start-from-zero/p/13659503.html
Copyright © 2011-2022 走看看