GaussDB(DWS) SQL进阶之数据类型(二)-字符类型

举报
你是猴子请来的救兵吗 发表于 2021/06/11 10:32:09 2021/06/11
【摘要】 字符类型是数据库中使用频率最高的数据类型之一,所以我们有必要深入了解各类型间的差异,以便在不同的场景选用合适的字符类型。

字符类型

首先介绍下GaussDB(DWS)支持的字符类型

名称 描述 长度 存储空间
CHAR(n)
CHARACTER(n)
NCHAR(n)
BPCHAR(n)
定长字符串,填充空格 字节长度,默认1,
小于10485761
最大为10MB
VARCHAR(n)
CHARACTER VARYING(n)
VARCHAR2(n)
变长字符串,小对象 字节长度,
小于10485761
最大为10MB
NVARCHAR2(n) 变长字符串,小对象 字符长度,
小于10485761
最大为10MB
TEXT
CLOB
变长字符串,大对象 - 最大为1GB-8203B

其中,NCHAR(n)、NVARCHAR2(n)、VARCHAR2(n)、CLOB是对Oracle兼容模式的增强。

此外,GaussDB(DWS)还有两种定长字符类型name、"char",通常用于系统内部,不推荐用户使用,这里不做介绍。

长度

如果把一个字段定义为char(n)或者varchar(n), 代表该字段最大可容纳n个长度的数据。无论哪种类型,可设置的最大长度都不得不超过10485760(即10M)。

当数据长度超过指定的长度n时,会抛出错误"value too long"。当然,也可通过指定数据类型,使超过长度的数据自动截断。

postgres=# create table t1 (a char(5),b varchar(5));
CREATE TABLE
-- 超出长度报错
postgres=# insert into t1 values('abcdefgh','123');
ERROR:  value too long for type character(5)
CONTEXT:  referenced column: a
-- 超过长度自动截断
postgres=# insert into t1 values('abcdefgh'::char(5),'12345678'::varchar(5));
INSERT 0 1
postgres=# select a,b from t1;
   a   |   b
-------+-------
 abcde | 12345
(1 row)

定长与变长

所有字符类型根据长度是否固定可归为定长字符串与变长字符串两大类。

对于定长字符串,长度必须确定,如果不指定长度,则默认长度1;如果数据长度不足,会在尾部自动填充空格,用以存储和显示;但这部分填充的数据是无意义的,实际使用中会被忽略,如比较、排序或类型转换。

对于变长字符串,若指定长度,则为最大可存储数据长度;如果不指定长度,则认为该字段支持任意长度。


postgres=# create table t2 (a char(5),b varchar(5));
CREATE TABLE
postgres=# insert into t2 values('abc','abc');
INSERT 0 1
-- 显示
postgres=# select a,lengthb(a),b from t2;
   a   | lengthb |  b
-------+---------+-----
 123   |       5 | 123
(1 row)
-- 比较
postgres=# select a = b from t2;
 ?column?
----------
 t
(1 row)
-- 转换
postgres=# select cast(a as text) as val,lengthb(val) from t2;
 val | lengthb
-----+---------
 123 |       3
(1 row)

字节数与字符数

VARCHAR2(n)和NVARCHAR2(n)中长度含义不同,需区别对待。VARCHAR2中为字节长度,NVARCHAR2中为字符长度。

以UTF8编码环境为例,字母占1个字节,汉字占3个字节,VARCHAR2(6)可以存放6个字母或2个汉字,而NVARCHAR2(6)可以存放6个字母或6个汉字。

postgres=# create table t3 (a varchar2(6),b nvarchar2(6));
CREATE TABLE
-- 超出长度报错
postgres=# insert into t3 values('大家好','a');
ERROR:  value too long for type character varying(6)
CONTEXT:  referenced column: a
postgres=# insert into t3 values('a','大家好abcd');
ERROR:  value too long for type nvarchar2(6)
CONTEXT:  referenced column: b
-- 保存成功
postgres=# insert into t3 values('大家','大家好abc');
INSERT 0 1
postgres=# select a,b from t3;
  a   |     b
------+-----------
 大家 | 大家好abc
(1 row)

存储空间

除了长度上的限制,存储中对元组中每列的内容大小也有限制,每个元组的总大小也不可超过1073733621B(即1GB-8203B)。

字符类型在系统内部使用varlena结构体存储数据,分别记录数据长度和内容,实际所需的存储需求是结构体头部加上实际的字串,如果是定长类型的话再加上填充的部分。

不同类型之间基本没有性能差别,只是定长字符串在填充空格时需要更多存储尺寸。

空串与NULL

Oracle兼容模式下,不区分空串与NULL,执行语句查询或数据导入时会将空串视为NULL。

由于空串默认被处理为NULL,那就不能使用 = '' 作为查询条件,也不能用 is ''。虽然不会有语法错误,但是不会有结果集返回。正确的用法是 is null,不等于就是 is not null 。

postgres=# create table t4 (a text);
CREATE TABLE
postgres=# insert into t4 values('abc'),(''),(null);
INSERT 0 3
-- 空串转为NULL
postgres=# select a,a isnull from t4;
  a  | isnull
-----+--------
 abc | f
     | t
     | t
(3 rows)
-- 用is null判断
postgres=# select a,a isnull from t4 where a is null;
  a  | isnull
-----+--------
     | t
     | t
(2 rows)

小结


对于字符串数据,建议使用变长字符串数据类型,并指定最大长度。请务必确保指定的最大长度大于需要存储的最大字符数,避免超出最大长度时出现字符截断现象。除非明确知道数据类型为固定长度字符串,否则,不建议使用CHAR(n)、BPCHAR(n)、NCHAR(n)、CHARACTER(n)等定长字符类型。

想了解GuassDB(DWS)更多信息,欢迎微信搜索“GaussDB DWS”关注微信公众号,和您分享最新最全的PB级数仓黑科技,后台还可获取众多学习资料哦~

dws博文.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。