MySql数据库varchar和java字符串length()长度tips

Java 中字符串以 Unicode 方式编码的, 其长度通常计算的是字符数,一个中文也算一个字符:

    public static void main(String[] args) {
        String fileName = "中文English,12345";//中文、英文、标点、数字都算一个字符
        int len = fileName.length();
        System.out.println("len="+ len);
    }

运行结果:

     len=15

MySql中 varchar(n)类型字段,n所表示的也是字符数,并非字节数,所以字段可以插入<=n个字符。一个字符占用多少

字节取决于所使用的字符编码,通常我使用UTF-8,Mysql中一个UTF-8编码的字符占3字节。例如:

CREATE TABLE `group_space` (
  `GROUP_ID` decimal(16,0) NOT NULL,
  `USER_FILE_ID` decimal(18,0) DEFAULT NULL,
  `USER_ID` decimal(20,0) DEFAULT NULL,
  `GROUP_SIZE` decimal(10,0) DEFAULT NULL,
  `CREATE_TIME` timestamp NULL DEFAULT NULL,
  `REVIEW_STATUS` decimal(1,0) DEFAULT NULL,
  `GROUP_NAME` varchar(5) DEFAULT NULL,
  `LAST_OPTIME` timestamp NULL DEFAULT NULL,
  `PUBLIC_LEVEL` decimal(1,0) DEFAULT NULL,
  `ENTER_LEVEL` decimal(1,0) DEFAULT NULL,
  `GROUP_NUMBER` varchar(20) DEFAULT NULL,
  `GROUP_MODEL` decimal(3,0) DEFAULT NULL,
  `GROUP_STATUS` decimal(1,0) DEFAULT NULL,
  `UNI_CONTACT_ID` decimal(20,0) DEFAULT NULL,
  PRIMARY KEY (`GROUP_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

其中GROUP_NAME字段,我定义了个较小的长度方便测试,长度为5,即可以插入5个字符,utf8编码最长存入

15字节。插入数据,给该GROUP_NAME字段赋值5个中文’我是中国人‘,sql如下:


INSERT INTO `group_space` (`GROUP_ID`, `USER_FILE_ID`, `USER_ID`, `GROUP_SIZE`, `CREATE_TIME`, `REVIEW_STATUS`, `GROUP_NAME`, 
`LAST_OPTIME`, `PUBLIC_LEVEL`, `ENTER_LEVEL`, `GROUP_NUMBER`, `GROUP_MODEL`, `GROUP_STATUS`, `UNI_CONTACT_ID`) 
VALUES ('113012502705', '413602500002', '8241', NULL, '2015-09-11 16:24:40', '1', 
'我是中国人', '2015-09-11 16:24:40', '2', '2', '113012502701', '200', '1', NULL);


执行无异常,结果:



同样的insert语句,GROUP_NAME增加一个字符’我是中国人a‘,赋值更换主键后再次执行,抛出异常:

[SQL]INSERT INTO `group_space` (`GROUP_ID`, `USER_FILE_ID`, `USER_ID`, `GROUP_SIZE`, `CREATE_TIME`, `REVIEW_STATUS`, `GROUP_NAME`, 
`LAST_OPTIME`, `PUBLIC_LEVEL`, `ENTER_LEVEL`, `GROUP_NUMBER`, `GROUP_MODEL`, `GROUP_STATUS`, `UNI_CONTACT_ID`) 
VALUES ('113012502706', '413602500002', '8241', NULL, '2015-09-11 16:24:40', '1', 
'我是中国人a', '2015-09-11 16:24:40', '2', '2', '113012502701', '200', '1', NULL);
[Err] 1406 - Data too long for column 'GROUP_NAME' at row 1


当服务出现类似因为字段长度不够的问题时,一般首先想到的是进行字段扩容。但是我负责的系统MySql是个分布式的集群,且数据量在亿级以上,而且出现较长字符串的场景只是偶尔外部原因导致,所以并没有采用字段扩容的方式解决该问题。直接在DAO层做了一个字符串截取,对超过数据库限制的GROUP_NAME字段做截取处理,保留前后一部分字符,去除中间部分,用“...”代替。字符串截取代码:

    public static void main(String[] args) {
        //fileName 字段进行截断(前7字符+...+后10字符)
        String fileName = "MySql数据库varchar长度tips-zhujinq.html";
            int maxLen = 20;
                if (StringUtils.isNotBlank(fileName) && fileName.length() > maxLen) {
                    int len = fileName.length();
                    fileName = fileName.substring(0, (maxLen/2)-3) + "..."+ fileName.substring(len-(maxLen/2), len);
                }
        
        System.out.println("fileName=" + fileName+", newLen=" + fileName.length());
    }


执行结果:

fileName=MySql数据...ujinq.html, newLen=20

最好的方式还是字段扩容。

你可能感兴趣的:(java,数据库SQL)