对于数据库字段类型的长度是看似简单的问题。但是却经常困扰着使用者。今天我用实践来验证为啥数据类型的长度要这样写。
一、官方字段类型使用说明
数据类型 | TDengine的说明 |
---|---|
VARCHAR | 存储可变长度的单字节字符串,只用于处理 ASCII 可见字符。VARCHAR 是 BINARY 的别称。 |
NCHAR | 存储可变长度的多字节字符串,如中文字符。等同于 MySQL 的 CHAR 和默认字符集(utf8)的 VARCHAR。 |
大白话就是:VARCHAR可以用来存储例如英文字母等一个字符只占用1个字节的字符串。并且还做了限制,只能存储ASCII 可见字符。
NCHAR可以用来存储例如汉字这样一个字符就占用2个字节的字符串。
思考:那么能不能给VARCHAR存储汉字,给NCHAR存储英文字母呢?
答案是:可以的。
但是,长度该是多少呢?下面我们用实践来证明:
二、字符串类型长度与存储内容的对照关系
1)给VARCHAR存储汉字
create stable testvarchar(ts TIMESTAMP, id bigint, name varchar(110)) Tags(class smallint);
insert into testvarcha01 values('2023-08-17 09:40:40', 1001, '按照上面的建表语句');
-- Query OK, 1 of 1 rows affected (0.026000s)
-- 9个汉字入库成功。
insert into testvarcha01 values('2023-08-17 09:40:43', 1003, '按照上面的建表语句存储多个语句总共需要多少字节呢按照上面的建表语句存储多个语句总共需要多少字节呢哈哈');
-- DB error: Value too long for column/tag: name (0.016000s)
-- 50个汉字。长度过程,存储失败。于是我们减少字符长度,再测试
insert into testvarcha01 values('2023-08-17 09:41:53', 1006, '按照上面的建表语句存储多个语句总共需要多少字节呢按照上面的建表语句到底是几');
-- Query OK, 1 of 1 rows affected (0.013000s)
-- 【直到减少到36个汉字时,入库成功!】
-- 查看数据
taos> select * from testvarchar;
ts | id | name | class |
============================================================================================
2023-08-17 09:40:40.000 | 1002 | 按照上面的建表语句 | 1 |
2023-08-17 09:40:41.000 | 1002 | 按照上面的建表语句存储多个... | 1 |
2023-08-17 09:40:43.000 | 1003 | 按照上面的建表语句存储多个... | 1 |
-- 再看看存入英文字母的情况:
insert into testvarcha01 values('2023-08-17 09:45:40', 1005, 'abcdefgaaadddsssdffffadfsdfsdfsfdfabcdefgaaadddsssdffffadfsdfsdfsfdfabcdefgaaadddsssdffffadfsdfsdfsfdfolpmjkiu1');
-- DB error: Value too long for column/tag: name (0.052000s)
-- 111个英文字母,未能入库成功。继续测试:
insert into testvarcha01 values('2023-08-17 09:45:40', 1005, 'abcdefgaaadddsssdffffadfsdfsdfsfdfabcdefgaaadddsssdffffadfsdfsdfsfdfabcdefgaaadddsssdffffadfsdfsdfsfdfolpmjkiu');
-- Query OK, 1 of 1 rows affected (0.009000s)
-- 【110个字母,存储成功!!】
VARCHAR(110)存入110个英文字母,我们可以理解。因为英文字母一个字符代表一个字节,110个字母刚好存入。
思考:那为啥只能存入36个汉字呢?
汉字不同的编码方式占用的字节数如下:
编码 | 1个英文字符 | 1个中文字符 |
---|---|---|
ASCII码 | 1字节 | 2个字节 |
UTF-8编码 | 1字节 | 3个字节 |
Unicode编码 | 2字节 | 2个字节 |
GB2312中文编码 | - | 2个字节 |
GBK编码 | - | 2个字节 |
可以看出如果是UTF-8编码,汉字是占3个字节的。 3 * 36 = 108个字节。接近110个字节的设定了。
思考:那我的Taos数据库是UTF-8编码吗?
立即查看taos.cfg文件,赫然显示默认编码是UTF-8:
# default system charset
# charset UTF-8
疑惑:那还差2个字节,去哪儿了?
TDengine数据类型章节说明了。
是不是因为这个原因呢?
存储英文字母时,却没有额外占用。或者说这里的额外占用并不包含在数据类型设定的长度内。
知道的小伙伴可以@我。谢谢。
我又尝试将这36个汉字转成ANSI编码,刚好是55个字符:
不知道TDegine是不是用ANSI编码了。
虽然上面我们验证了VARCHAR存储汉字的长度和存储。但是官方还是建议不要存储汉字:
官方说:
2)给NCAHR存储英文字母
上面我们验证了VARCHAR存储汉字,下面我们验证NCAHR存储汉字和英文字母的情况:
-- 我们新增一列name2,长度设置10
alter stable testvarchar add column name2 nchar(10);
-- Query OK, 0 of 0 rows affected (0.011000s)
insert into testvarcha01 values('2023-08-17 09:42:53', 1008, 'abc110个', '这里只能存储十个汉字吗');
-- DB error: Value too long for column/tag: name2 (0.048000s)
-- 插入11个汉字,果然超长了!
insert into testvarcha01 values('2023-08-17 09:42:53', 1008, 'abc110个', '这里只能存储十个汉字');
-- Query OK, 1 of 1 rows affected (0.021000s)
-- 10个汉字成功了!
-- 查看数据
select * from testvarchar;
ts | id | name | name2 | class |
=============================================================================================================================
2023-08-17 09:42:53.000 | 1008 | abc110个 | 这里只能存储十个汉字 | 1 |
-- 再测试插入因为的情况
insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesomewordorany');
-- DB error: Value too long for column/tag: name2 (0.027000s)
taos> insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesomewordoran');
-- DB error: Value too long for column/tag: name2 (0.047000s)
taos> insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesomewordo');
-- DB error: Value too long for column/tag: name2 (0.013000s)
taos> insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesomewor');
-- DB error: Value too long for column/tag: name2 (0.023000s)
taos> insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesomewo');
-- DB error: Value too long for column/tag: name2 (0.025000s)
taos> insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesomew');
-- DB error: Value too long for column/tag: name2 (0.013000s)
taos> insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesome');
-- DB error: Value too long for column/tag: name2 (0.029000s)
taos> insert into testvarcha01 values('2023-08-17 09:43:53', 1009, 'abc110个', 'cansavesom');
-- Query OK, 1 of 1 rows affected (0.051000s)
-- 【从20个字母,一直尝试到10个字母,才成功入库!!!】
-- // 理想很丰满,显示很骨干!
经过一番测试。我们发现NCAHR简直就是个“老死板”,说好的10个,哪管你是汉字还是英文字母,就只能插入10个字符。爱咋咋地吧🤣
官方数据类型说明是:
看起来这个多字节字符也包含单字节字符。😥
三、小结
数据类型 | 建议存储 | 不建议存储 |
---|---|---|
VARCHAR | 单字符字符串,如英文字母。 | 汉字字符串 |
NCHAR | 多字符字符串,如汉字。 | 英文字符串 |
用什么数据库都可以。但是我们一定要遵守相关规范。合理的利用数据类型,这样才能达到最佳效果呀。