zoukankan      html  css  js  c++  java
  • Mysql 和 Oralce中char(n) 的不同

    1. 总结
      1. Mysql 测试
      2. Oracle 测试
      3. 为什么Mysql utf8mb4 varchar(最大16383)
      4. Latin1 字符集的存储

    总结:
    1.Mysql 中的char(n) n表示字符串长度。表示最多存储n个字符,无论字符是中文英文还是数字。如char(6) 可以存储 '你好数你最棒','123456','abcdef',但不能存储'1234567'
    2.Oracle 中的char(n) n表示字节数。如ZHS16GBK下,一个汉字占用两个字节,一个字符占用1个字节。char(6) 存储 '你好数你'就存不下了,存储英文或数字没问题
    varchar 可采用相同的理解方式

    1. Mysql 测试

    char(n) n表示字符串长度

    环境
    Mysql 8.0.16
    Charset utf8mb4

    mysql> select version();
    +-----------+
    | version() |
    +-----------+
    | 8.0.16    |
    +-----------+
    1 row in set (0.00 sec)
    
    mysql> show create table t1;
    +-------+----------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                         |
    +-------+----------------------------------------------------------------------------------------------------------------------+
    | t1    | CREATE TABLE `t1` (
      `name` char(6) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
    +-------+----------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
    
    mysql> insert into t1 values('你好数你最棒');
    Query OK, 1 row affected (0.00 sec)
    mysql> insert into t1 values('你好数你最棒a');
    ERROR 1406 (22001): Data too long for column 'name' at row 1
    
    mysql> insert into t1 values('123456');
    Query OK, 1 row affected (0.02 sec)
    mysql> insert into t1 values('1234567');
    ERROR 1406 (22001): Data too long for column 'name' at row 1
    
    mysql> insert into t1 values('abcdef');
    Query OK, 1 row affected (0.00 sec)
    mysql> insert into t1 values('abcdefg');
    ERROR 1406 (22001): Data too long for column 'name' at row 1
    
    mysql> select * from t1;
    +--------------------+
    | name               |
    +--------------------+
    | 你好数你最棒         |
    | 123456             |
    | abcdef             |
    +--------------------+
    3 rows in set (0.00 sec)
    

    2. Oracle 测试

    char(n) n表示字节数

    环境
    Oracle 11.2.0.4
    字符集 ZHS16GBK 一个汉字占用两个字节,一个字符占用1个字节

    SQL> select * from v$version;
    BANNER
    --------------------------------------------------------------------------------
    Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
    PL/SQL Release 11.2.0.4.0 - Production
    CORE	11.2.0.4.0	Production
    TNS for Linux: Version 11.2.0.4.0 - Production
    NLSRTL Version 11.2.0.4.0 - Production
    
    SQL> select userenv('language') from dual;
    
    USERENV('LANGUAGE')
    ----------------------------------------------------
    SIMPLIFIED CHINESE_CHINA.ZHS16GBK
    
    SQL> create table t_oracle (name char(6));
    
    Table created
    
    SQL> insert into t_oracle values('中华人');
    
    1 row inserted
    
    SQL> insert into t_oracle values('中华人民');
    
    insert into t_oracle values('中华人民')
    
    ORA-12899: 列 "CYM"."T_ORACLE"."NAME" 的值太大 (实际值: 8, 最大值: 6)
    
    SQL> insert into t_oracle values('abcdef');
    
    1 row inserted
    
    SQL> insert into t_oracle values('abcdefg');
    
    insert into t_oracle values('abcdefg')
    
    ORA-12899: 列 "CYM"."T_ORACLE"."NAME" 的值太大 (实际值: 7, 最大值: 6)
    
    SQL> insert into t_oracle values('123456');
    
    1 row inserted
    
    SQL> insert into t_oracle values('1234567');
    
    insert into t_oracle values('1234567')
    
    ORA-12899: 列 "CYM"."T_ORACLE"."NAME" 的值太大 (实际值: 7, 最大值: 6)
    
    SQL> commit;
    
    Commit complete
    
    SQL> select * from t_oracle;
    
    NAME
    ------
    中华人
    abcdef
    123456
    

    所以这也能理解为什么 utf8mb4 下, varchar 最大长度是 16383了。

    3. 为什么Mysql utf8mb4 varchar(最大16383)

    mysql> create table t1_1(name varchar(65535));              
    ERROR 1074 (42000): Column length too big for column 'name' (max = 16383); use BLOB or TEXT instead
    
    mysql> create table t1_1(name varchar(16383));
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> select 65535/4;
    +------------+
    | 65535/4    |
    +------------+
    | 16383.7500 |
    +------------+
    1 row in set (0.03 sec)
    

    因为Mysql 有硬性规定每行的最大大小是65535 Bytes。可参考Mysql8.0 参考手册
    而utf8mb4字符集下每个字符的最大存储时4 Byte,要满足varchar(16384)能存储16384个字符,就需要16384*4(Bytes)=65536(Bytes)>65535(Bytes)的存储空间,这是冲突的。

    所以utfmb4 下Mysql 单个字符串最长(16383),这还是在没有其他字段的情况下。官方说的是单行65535,而不是每个字段65535。如下就失败:

    mysql> create table t1_2(name1 varchar(8000),name2 varchar(8384));
    ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
    mysql> create table t1_2(name1 varchar(8000),name2 varchar(8383));
    ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
    mysql> create table t1_2(name1 varchar(8000),name2 varchar(8382));
    Query OK, 0 rows affected (0.02 sec)
    

    第二行创建失败,是因为varchar的存储是:长度位+实际数据。n<=255 长度位=1Byte,n>255 长度位=2Bytes
    所以 80004+2+83834+2=65536>65535 创建失败。

    虽然utf8mb4 支持的长度不长,但是我们还是要使用utf8mb4,因为它是真正的 UTF-8 字符集,支持最多的字符,支持emoji,支持特殊的汉字,而其他字符集有遇到乱码的可能。千万注意!

    4. Latin1 字符集的存储

    Latin1 是一个单字节字符集,每个字符只占用1Bytes,不能存储汉字。

    mysql> create table t2(name char(10))charset latin1; 
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> insert into t2 values('鼠');
    ERROR 1366 (HY000): Incorrect string value: 'xE9xBCxA0' for column 'name' at row 1
    
    mysql> create table t2_1(name varchar(65533)) charset latin1;
    ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
    mysql> create table t2_1(name varchar(65532)) charset latin1; 
    Query OK, 0 rows affected (0.05 sec)
    

    Latin1 65532+2=65534 Bytes,另一个字节存什么去了?另一个字节是可为空值的标志位。

    mysql>  create table t2_1(name varchar(65533) not null) charset latin1; 
    Query OK, 0 rows affected (0.04 sec)
    
  • 相关阅读:
    linux查看端口被占用等常用命令
    python批量修改文件内容及文件编码方式的处理
    为什么在Python里推荐使用多进程而不是多线程
    python小练习之读取文件写入excel
    python 小练习之生成手机号码
    python 小练习之删除文件夹下的所有文件,包括子文件夹中的文件
    python中 字符 字典 列表之间的转换
    统计表中 重复出现 XX次以上的数据
    java数据类型
    字符编码和python使用encode,decode转换utf-8, gbk, gb2312
  • 原文地址:https://www.cnblogs.com/plluoye/p/12195563.html
Copyright © 2011-2022 走看看