
# 字符类型
DWS支持的字符类型请参见[表1]。字符串操作符和相关的内置函数请参见[字符串处理函数和操作符](https://support.huaweicloud.com/sqlreference-911-dws/dws_06_0030.html)。
 表1字符类型 
| 名称                                                                                                                                                                                                                                 | 描述                                  | 长度                                 | 存储空间                         |
|:---|:---|:---|:---|
| CHAR(n)或BPCHAR CHARACTER(n) NCHAR(n) | 定长字符串，超出会截断，不足填充空格。                 | n是指字节长度，如不带精度n，默认精度为1。n小于10485761。 | 最大为10MB。                     |
| VARCHAR(n) CHARACTER VARYING(n)                                                                                                     | 变长字符串。                              | n是指字节长度，n小于10485761。               | 最大为10MB。                     |
| VARCHAR2(n)                                                                                                                                                                                                                        | 变长字符串。是VARCHAR(n)类型的别名，为兼容Oracle类型。 | n是指字节长度，n小于10485761。               | 最大为10MB。                     |
| NVARCHAR2(n)                                                                                                                                                                                                                       | 变长字符串。                              | n是指字符长度，n小于10485761。               | 最大为10MB。                     |
| CLOB                                                                                                                                                                                                                               | 变长字符串。文本大对象。是TEXT类型的别名，为兼容Oracle类型。 | -                                  | 最大为1GB-8203B （即1073733621B）。 |
| TEXT                                                                                                                                                                                                                               | 变长字符串。                              | -                                  | 最大为1GB-8203B（即1073733621B） 。 |
   
![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/note_3.0-zh-cn.png)
- 除了每列的大小限制以外，每个元组的总大小也不可超过1GB-8203B（即1073733621B）。
- 对于字符串数据，建议使用变长字符串数据类型，并指定最大长度。请务必确保指定的最大长度大于需要存储的最大字符数，避免超出最大长度时出现字符截断现象。除非明确知道数据类型为固定长度字符串，否则，不建议使用CHAR(n)、NCHAR(n)、CHARACTER(n)等定长字符类型。在DWS中，定长字符类型的运算会存在额外的存储和内存开销。
- 一般情况下，如果含有中文字符，用NCHAR/NVARCHAR2，如果纯英文和数字，用CHAR/VARCHAR。
  
 
在DWS里另外还有两种定长字符类型。在[表2]里显示。
其中，name类型只用在内部系统表中，作为存储标识符，该类型长度当前定为64字节（63可用字符加结束符）。不建议普通用户使用这种数据类型。name类型与其他数据类型进行对齐时（比如case when的多个分支中，其中一个分支返回name类型，其他类型返回text类型），可能会出现向name类型对齐，字符截断。如果不希望出现字符按照64位截断的情况，则需要将name类型强制类型转化为text类型。
类型"char"只用了一个字节的存储空间。它在系统内部主要用于系统表，主要作为简单化的枚举类型使用。
 表2特殊字符类型 
| 名称     | 描述          | 存储空间  |
|:---|:---|:---|
| name   | 用于对象名的内部类型。 | 64字节。 |
| "char" | 单字节内部类型。    | 1字节。  |
   
#### 长度
如果把一个字段定义为char(n)或者varchar(n)， 代表该字段最大可容纳n个长度的数据。无论哪种类型，可设置的最大长度都不得超过10485760（即10MB）。
当数据长度超过指定的长度n时，会抛出错误"value too long"。也可通过指定数据类型，使超过长度的数据自动截断。
示例：
1. 创建表t1，指定其字段的字符类型。
   ```
   CREATE TABLE t1 (a char(5),b varchar(5));
   ```
   
2. 向表t1插入数据时超过指定的字节长度报错。
   ```
   INSERT INTO t1 VALUES('bookstore','123');
   ERROR:  value too long for type character(5)
   CONTEXT:  referenced column: a
   ```
   
3. 向表t1插入数据并明确超过指定字节长度后自动截断。
   ```
   INSERT INTO t1 VALUES('bookstore'::char(5),'12345678'::varchar(5));
   INSERT 0 1
   SELECT a,b FROM t1;
      a   |   b
   -------+-------
    books | 12345
   (1 row)
   ```
   
 
#### 定长与变长
所有字符类型根据长度是否固定可以分为定长字符串与变长字符串两大类。
- 对于定长字符串，长度必须确定，如果不指定长度，则默认长度1；如果数据长度不足，会在尾部自动填充空格，用于存储和显示；但这部分填充的数据是无意义的，实际使用中会被忽略，如比较、排序或类型转换。
- 对于变长字符串，若指定长度，则为最大可存储数据长度；如果不指定长度，则认为该字段支持任意长度。
示例：
1. 创建表t2，指定其字段的字符类型。
   ```
   CREATE TABLE t2 (a char(5),b varchar(5));
   ```
   
2. 向表t2插入数据并查询字段a的字节长度。因建表时指定a的字符类型为char(5)且是定长字符串，长度不足，填充空格，所以查询的字节长度为5。
   ```
   INSERT INTO t2 VALUES('abc','abc');
   INSERT 0 1
   SELECT a,lengthb(a),b FROM t2;
      a   | lengthb |  b
   -------+---------+-----
    abc   |       5 | abc
   (1 row)
   ```
   
3. 用函数转换后查询字段a的实际字节长度为3。
   ```
   SELECT a = b from t2;
    ?column?
   ----------
    t
   (1 row)
   SELECT cast(a as text) as val,lengthb(val) FROM t2;
    val | lengthb
   -----+---------
    abc |       3
   (1 row)
   ```
   
 
#### 字节数和字符数
VARCHAR2(n)和NVARCHAR2(n)中长度含义不同，需区别对待。
- VARCHAR2中n为字节长度。
- NVARCHAR2中n为字符长度。
  ![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/note_3.0-zh-cn.png)
  以UTF8编码的数据库为例，字母占1个字节，汉字占3个字节，VARCHAR2(6)可以存放6个字母或2个汉字，而NVARCHAR2(6)可以存放6个字母或6个汉字。
  
示例：
1. 创建表t3，指定其字段的字符类型。
   ```
   CREATE TABLE t3 (a varchar2(6),b nvarchar2(6));
   ```
   
2. 向表t3插入数据，超出长度报错。（以UTF8字符编码的数据库中操作为例）
   ```
   INSERT INTO t3 values('产品名','auto');
   ERROR:  value too long for type character varying(6)
   CONTEXT:  referenced column: a
   INSERT INTO t3 values('auto','产品名abcd');
   ERROR:  dn_6003_6004: value too long for type nvarchar2(6)
   CONTEXT:  referenced column: b
   ```
   
3. 调整插入数据长度后向表t3插入数据成功。
   ```
   INSERT INTO t3 values('产品','产品名abc');
   INSERT 0 1
   SELECT a,b from t3;
     a   |     b
   ------+-----------
    产品 | 产品名abc
   ```
   
#### 空串与NULL
Oracle兼容模式下，不区分空串与NULL，执行语句查询或数据导入时会将空串处理为NULL。
由于空串默认被处理为NULL，那就不能使用 = '' 作为查询条件，也不能用is ''。虽然不会有语法错误，但是不会有结果集返回。正确的用法是is null，不等于就是is not null 。
示例：
1. 创建表t4，指定其字段的字符类型。
   ```
   CREATE TABLE t4 (a text);
   ```
   
2. 向表t4插入数据，插入值中包含空串和NULL。
   ```
   INSERT INTO t4 VALUES('abc'),(''),(null);
   INSERT 0 3
   ```
   
3. 查询表t4中是否存在空值。
   ```
   SELECT a,a isnull FROM t4;
     a  | ?column?
   -----+----------
        | t
        | t
    abc | f
   (3 rows)
   SELECT a,a isnull FROM t4 WHERE a is null;
    a | ?column?
   ---+----------
      | t
      | t
   (2 rows)
   ```
   
   
TD与MySQL兼容模式下，区分空串与null。
- TD兼容模式下示例：
  ```
  SELECT  '' is null , null is null;
   isnull |  isnull
  --------+----------
   f      | t
  (1 row)
  ```
  

- MySQL兼容模式下示例：
  ```
  SELECT  '' is null , null is null;
   isnull |  isnull
  --------+----------
   f      | t
  (1 row)
  ```
  
 
