• Sql Server中的nvarchar(n)、varchar(n) 和Mysql中的char(n)、varchar(n)


      刚才有幸看了下 nvarchar(n)和varchar(n),感觉以前的认知有误。

      nvarchar(n):n指的是字符个数,范围是1-4000,存储的是可变长度的Unicode字符数据。

            按字符存储,1个中文或者英文字符都占2个字节。

      varchar(n):n指的是字节个数(其实这个地方用【字符】也行,1个字符占一个字节),范围是1-8000,存储的是可变长度的非Unicode字符数据。

            按字节存储,1个中文或者英文字符都占1个字节。

      实验例子:创建一个People2表,有字段UName,数据类型为varchar(2);字段Age,数据类型为nvarchar(2)。

       

      1.测试varchar(2)

      (1).Uname列里插入1个汉字或1个英文

      结果:全部成功

      

       (2).Uname列里插入2个汉字或2个英文

      结果:2个英文的成功,2个汉字的失败

      

      

       (2).Uname列里插入1个汉字和1个英文

      结果:失败

      

    总结:在varchar(2)中,2表示最大可以存两个字节,即能存1个汉字符号,或者2个英文符号。1个汉字符号占2个字节,1个英文符号占1个字节。

      

      2.测试nvarchar(2)

        (1).Age列里插入1个汉字或1个英文

      结果:都成功

      

      (2).Age列里插入2个汉字或2个英文

      结果:都成功

      

      (3).Age列里插入1个汉字和1个英文

      结果:成功

      

       (4).Age列里插入1个汉字和2个英文

      结果:失败

    总结:在nvarchar(2)中,2表示最大可以存两个字符,即能存2个汉字符号,或者2个英文符号。1个汉字符号占2个字节,1个英文符号占2个字节。

    其他:varchar中也能存储汉字,但是,但是,但是遇到一些生僻汉字时有可能会乱码。

    ------------------------------------------------------------------Mysql中的char(n)和varchar(n)-------------------------------------------------------------- 

       在Mysql中,存在着char和varchar两种字符串类型,并没有所谓的nvarchar。以下结论基于Mysql5.0版本以上:

          

        为了做实验,先准备下三个不同字符集的数据表。

    mysql>  create table tb_latin (a_char char(2),b_varchar varchar(2)) default character set latin1;  
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show create table tb_latin;
    +----------+-----------------------------------------------------------------------------------------------------------------------------------------+
    | Table    | Create Table                                                                                                                            |
    +----------+-----------------------------------------------------------------------------------------------------------------------------------------+
    | tb_latin | CREATE TABLE `tb_latin` (
      `a_char` char(2) DEFAULT NULL,
      `b_varchar` varchar(2) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
    +----------+-----------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql>  create table tb_gbk (a_char char(2),b_varchar varchar(2)) default character set gbk;  
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> show create table tb_gbk;
    +--------+------------------------------------------------------------------------------------------------------------------------------------+
    | Table  | Create Table                                                                                                                       |
    +--------+------------------------------------------------------------------------------------------------------------------------------------+
    | tb_gbk | CREATE TABLE `tb_gbk` (
      `a_char` char(2) DEFAULT NULL,
      `b_varchar` varchar(2) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=gbk |
    +--------+------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    mysql>  create table tb_utf8 (a_char char(2),b_varchar varchar(2)) default character set utf8 ;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show create table tb_utf8;
    +---------+--------------------------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                                         |
    +---------+--------------------------------------------------------------------------------------------------------------------------------------+
    | tb_utf8 | CREATE TABLE `tb_utf8` (
      `a_char` char(2) DEFAULT NULL,
      `b_varchar` varchar(2) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
    +---------+--------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    View Code

       

     char(n)

     1.往tb_latin表中插入数据。

    mysql>  insert into  tb_latin (a_char) values  ('z');
    mysql>  insert into  tb_latin (a_char) values  ('zz');
    mysql>  insert into  tb_latin (a_char) values  ('');       #latin1字符集下不支持中文,所以报错。
    ERROR 1366 (HY000): Incorrect string value: 'xE4xB8xAD' for column 'a_char' at row 1

                 查询出字符串的所占字节数(length),字符串长度(char_length)。

    mysql>  select a_char,length(a_char),CHAR_LENGTH(a_char)  from  tb_latin;
    +--------+----------------+---------------------+
    | a_char | length(a_char) | CHAR_LENGTH(a_char) |
    +--------+----------------+---------------------+
    | z      |              1 |                   1 |
    | zz     |              2 |                   2 |
    +--------+----------------+---------------------+
    2 rows in set (0.00 sec) 

         结论:latin1字符集中,1个字符占一个字节。不支持中文字符。

      

     2.往tb_gbk表中插入数据。

    mysql>  insert into  tb_gbk (a_char) values  ('zz');
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into  tb_gbk (a_char) values  ('');
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into  tb_gbk (a_char) values  ('z中');
    Query OK, 1 row affected (0.01 sec)
    
    mysql>  insert into  tb_gbk (a_char) values  ('中中');
    Query OK, 1 row affected (0.00 sec)

          查询出字符串的所占字节数(length),字符串长度(char_length)。

    mysql> select a_char,length(a_char),CHAR_LENGTH(a_char)  from  tb_gbk;
    +--------+----------------+---------------------+
    | a_char | length(a_char) | CHAR_LENGTH(a_char) |
    +--------+----------------+---------------------+
    | z      |              1 |                   1 |
    | zz     |              2 |                   2 |
    ||              2 |                   1 |
    | z中    |              3 |                   2 |
    | 中中   |              4 |                   2 |
    +--------+----------------+---------------------+

      结论:gbk字符集中,1个英文字符占一个字节,一个中文字符占两个字节。char(2),可以存2个英文占两个字节,2个中文占四个字节,1个英文和1个中文,占三个字节。

     

     3.往tb_utf8表中插入数据。

    mysql>  insert into  tb_utf8 (a_char) values  ('z');
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into  tb_utf8 (a_char) values  ('zz');
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into  tb_utf8 (a_char) values  ('');
    Query OK, 1 row affected (0.01 sec)
    
    mysql>  insert into  tb_utf8 (a_char) values  ('z中');
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into  tb_utf8 (a_char) values  ('中中');
    Query OK, 1 row affected (0.01 sec)

       查询出字符串的所占字节数(length),字符串长度(char_length)。

    
    
    mysql>  select a_char,length(a_char),CHAR_LENGTH(a_char)  from  tb_utf8;
    +--------+----------------+---------------------+
    | a_char | length(a_char) | CHAR_LENGTH(a_char) |
    +--------+----------------+---------------------+
    | z      |              1 |                   1 |
    | zz     |              2 |                   2 |
    ||              3 |                   1 |
    | z中    |              4 |                   2 |
    | 中中   |              6 |                   2 |
    +--------+----------------+---------------------+
    
    

    结论:utf8字符集中,1个英文字符占一个字节,一个中文字符占三个字节。char(2),可以存2个英文占两个字节,2个中文占六个字节,1个英文和1个中文,占四个字节。

     

    4.char(n),n的最大值

       n的最大值是255,而且跟字符集编码无关,进行验证。

    mysql> alter table tb_latin add charmax1 char(255);
    Query OK, 0 rows affected (0.06 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> alter table tb_latin add charmax2 char(256);
    ERROR 1074 (42000): Column length too big for column 'charmax2' (max = 255); use BLOB or TEXT instead
    mysql> 
    mysql> alter table tb_gbk add charmax1 char(255);
    Query OK, 0 rows affected (0.03 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> 
    mysql> alter table tb_gbk add charmax2 char(256);
    ERROR 1074 (42000): Column length too big for column 'charmax2' (max = 255); use BLOB or TEXT instead
    mysql> alter table tb_utf8 add charmax1 char(255);
    Query OK, 0 rows affected (0.03 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> 
    mysql> alter table tb_utf8 add charmax2 char(256);
    ERROR 1074 (42000): Column length too big for column 'charmax2' (max = 255); use BLOB or TEXT instead

    结论:char类型的最大长度为255,这个最大值与字符集编码无关。

    SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';

      注意:char中有很大的一个特性就是,char(2)中,当字符长度没有达到2个时,会用空格补全余下的字符,但是上述实验却体现不出来。原因是sql_mode没有开启PAD_CHAR_TO_FULL_LENGTH,默认情况下,尾部空格CHAR在检索时从列值中删除 。如果 PAD_CHAR_TO_FULL_LENGTH启用,则不会发生修剪,并将检索 CHAR值填充到其全长。

      

      mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';              #设置sql_mode
      Query OK, 0 rows affected (0.00 sec)

    mysql>  select a_char,length(a_char),CHAR_LENGTH(a_char)  from  tb_utf8;
    +--------+----------------+---------------------+
    | a_char | length(a_char) | CHAR_LENGTH(a_char) |
    +--------+----------------+---------------------+
    | z      |              2 |                   2 |              #可以发现char的字符长度都是2了
    | zz     |              2 |                   2 |
    ||              4 |                   2 |
    | z中    |              4 |                   2 |
    | 中中   |              6 |                   2 |
    +--------+----------------+---------------------+ 

    varchar(n)
      1.varchar中,字符串占用空间是实际字符长度占用的空间,长度不足n时,也不会用空格补全,在不同字符集中,汉字英文占用的长度和char中的一样。
       2.但就是n的最大值问题,与字符集编码有关。
     
     在latin字符集下,如果varchar的字段可以为空,则最大是65532,若不可以为空,最大值是65533.
    mysql> create table test(name varchar(65532))engine=innodb DEFAULT CHARSET=latin1; 
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> drop table if exists test; 
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> create table test(name varchar(65533) not null)engine=innodb DEFAULT CHARSET=latin1; 
    Query OK, 0 rows affected (0.02 sec)
    
    

           

     在gbk字符集下, varchar 最大是32766, 这次与是否为空没有关系.
    
    
    mysql> create table test(name varchar(32766))engine=innodb DEFAULT CHARSET=gbk; 
    Query OK, 0 rows affected (0.02 sec)
     
    mysql> drop table if exists test; 
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> create table test(name varchar(32766) not null)engine=innodb DEFAULT CHARSET=gbk; 
    Query OK, 0 rows affected (0.01 sec)
    
    
     在utf8字符集下, varchar 最大是21844, 这次与是否为空没有关系.
    
    
    mysql> create table test(name varchar(21844))engine=innodb DEFAULT CHARSET=utf8; 
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> drop table if exists test; 
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> create table test(name varchar(21844) not null)engine=innodb DEFAULT CHARSET=utf8; 
    Query OK, 0 rows affected (0.02 sec)
    
    
    
     参考:1.https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_pad_char_to_full_length
       2.
    mysql 编码和汉字存储占用字节问题的探索
    3.关于mysql中的int(N)、char(N)和varchar(N)类型的简单说明
     
  • 相关阅读:
    servlet生命周期和线程安全
    如何保证Redis与数据库的数据一致性
    消息队列高可用、幂等性、顺序性、可靠性传输、堆积问题解决
    如何保证消息队列消息的顺序性
    RabbitMQ 如何保证消息不丢失?
    深入理解MySql事务
    MySQL/mariadb知识点总结
    如何实现一个线程安全的单例,前提是不能加锁
    DUBBO原理、应用与面经总结
    SpringBoot中资源初始化加载的几种方式
  • 原文地址:https://www.cnblogs.com/sdadx/p/7908415.html
Copyright © 2020-2023  润新知