文档首页/ 数据仓库服务 DWS/ 最佳实践/ 数据开发/ 使用GB18030字符集解决生僻字和少数民族文字无法识别问题
更新时间:2026-01-22 GMT+08:00
分享

使用GB18030字符集解决生僻字和少数民族文字无法识别问题

在业务日常开发过程中处理中文文本时,我们经常遇到gbk字符集由于字符范围有限,导致生僻字和少数民族文字无法正确识别的问题,这不仅影响了用户体验,也不符合《信息技术产品国家通用语言文字使用管理规定》的要求。

为了解决这一问题,DWS在9.1.1.100版本新增支持了GB18030字符集功能,支持更广泛字符集的编码方式,它能够覆盖绝大部分的字符,包括生僻字和少数民族文字,从而满足国家规定的要求,同时提升用户体验。

约束限制

该功能仅9.1.1.100及以上的集群版本支持。

GB18030编码介绍

GB18030采用1/2/4字节变长编码结构,对应的编码范围如表1所示。

表1 GB18030编码结构

字节数

编码范围

字符类型

1字节

0x00-0x7F

ASCII兼容字符

2字节

0x81-0xFE 0x40-0x7E/0x80-0xFE

基本汉字区(20902字)

4字节

0x81-0xFE 0x30-0x39 0x81-0xFE 0x30-0x39

扩展区(70,000+汉字)

常用汉字编码示例:

1
2
3
"中" -> 0xD6D0 (2字节)
"䶮" -> 0x9835FC39 (4字节)
"𠀀" -> 0x90308130 (4字节, CJK扩展B区)

GB18030版本演进情况如表2所示:

表2 版本演进

特性

GB18030-2000

GB18030-2005

GB18030-2022

汉字数量

27,533

70,244

87,887

支持Unicode版本

3.0

4.0

11.0

新增字符

CJK扩展A

CJK扩展B

CJK扩展C-G

少数民族文字

基本支持

增强支持

完整支持

部首支持

228部首

GB18030相比于GBK字符集,在支持汉字数量和种类上,都有明显扩展。

表3 GB18030与GBK对比

维度

GBK

GB18030

编码空间

23940字符

160万+字符

字节结构

固定双字节

1/2/4字节变长

Unicode映射

部分支持

完全支持

生僻字支持

< 10%

100%覆盖

少数民族文字

不支持

完整支持(苗文、傈僳文等)

Emoji支持

完整支持(✅等)

DWS对GB18030的支持范围

  • 字符集:完整支持87,887汉字+228部首
  • 少数民族文字
    • 滇东北苗文 (U+16F00-U+16F9F)
    • 傈僳文 (U+A4D0-U+A4FF)
    • 西夏文 (U+17000-U+187FF)
  • 特殊符号
    • 易经八卦符号 (U+4DC0-U+4DFF)
    • 太玄经符号 (U+1D300-U+1D35F)
    • 麻将牌符号 (U+1F000-U+1F02F)

基本创建语法

创建字符集编码为GB18030的数据库。

1
2
3
4
5
6
CREATE DATABASE gb18030_db
    ENCODING = 'GB18030'
    LC_COLLATE = 'zh_CN.GB18030'
    LC_CTYPE = 'zh_CN.GB18030'
    DBCOMPATIBILITY = 'TD'
    TEMPLATE = template0;
  • LC_COLLATE: 指定数据库使用的字符集。例如,gbk编码通过lc_collate=‘zh_CN.gbk’,utf8通过lc_collate=‘en_us.utf8’,gb18030/gb18030-2022通过lc_collate=‘zh_CN.GB18030’。该参数的使用会影响到对字符串的排序顺序,可以通过查pg_collate表找到对应编码的lc_collate。
  • LC_CTYPE:指定新数据库使用的字符分类。例如,通过lc_ctype = 'zh_CN.gbk’设定该参数。该参数的使用会影响到字符的分类,如大写、小写和数字。默认是使用模板数据库的字符分类。
  • ENCODING:指定数据库字符集,固定为GB18030。
  • DBCOMPATIBILITY:兼容Teradata语法。
创建支持GB18030的表。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-- 普通表
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL COLLATE "zh_CN.gb18030",
    id_card CHAR(18) COLLATE "zh_CN.gb18030"
);

-- 分区表示例
CREATE TABLE census_data (
    region_code CHAR(6),
    family_name VARCHAR(20) COLLATE "zh_CN.gb18030",
    population INT
) PARTITION BY range(population)
(PARTITION p1 START(1) END(10) EVERY(1));

为特定列设置排序规则。

1
2
ALTER TABLE users 
ALTER COLUMN name TYPE VARCHAR(50) COLLATE "zh_CN.gb18030";

查看当前排序规则。

1
2
3
4
SELECT a.attname, c.collname 
FROM pg_attribute a
JOIN pg_collation c ON a.attcollation = c.oid
WHERE a.attrelid = 'users'::regclass;

使用场景:插入和查询生僻字

  1. 创建字符集编码为GB18030的数据库。

    1
    2
    3
    4
    5
    6
    CREATE DATABASE gb18030_db
        ENCODING = 'GB18030'
        LC_COLLATE = 'zh_CN.GB18030'
        LC_CTYPE = 'zh_CN.GB18030'
        DBCOMPATIBILITY = 'TD'
        TEMPLATE = template0;
    

  2. 连接到新创建的gb18030_db数据库下,创建测试表rare_characters。

    1
    2
    3
    4
    5
    CREATE TABLE rare_characters (
        id SERIAL PRIMARY KEY,
        character TEXT COLLATE "zh_CN.gb18030",
        unicode_point VARCHAR(10)
    );
    

  3. 设置客户端字符编码为GB18030。

    1
    SET client_encoding = 'GB18030';
    

  4. 插入生僻字。

    1
    2
    3
    4
    INSERT INTO rare_characters (character, unicode_point) VALUES
    ('䶮', 'U+4DAE'), -- GB18030编码: 0x9835FC39
    ('𰾅', 'U+30F85'),-- CJK扩展G区
    ('', 'U+31350'); -- 傈僳文字符
    

  5. 查询验证。

    1
    SELECT * FROM rare_characters  WHERE character = '䶮';
    

GDS数据迁移流程

本样例重点突出GDS外表样例,详细GDS外表迁移流程参见使用GDS从远端服务器上导入表数据到DWS集群

  1. 启动GDS服务。

    1
    gds -d /data/gds_dir -p ip:port -H address_string -l log_file -D -t worker_num
    

  2. 创建GDS外表,其中字符集编码encoding设置成GB18030。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    CREATE FOREIGN TABLE gb18030_import (
        id INT,
        full_name TEXT,
        address TEXT
    ) SERVER gsmpp_server OPTIONS (
        location 'gsfs://ip:port/filepwd',
        format 'text',
        delimiter '|',
        encoding 'GB18030',
        compatible_illegal_chars 'true',
        replace_illegal_chars '',
        fill_missing_fields 'true',
        ignore_extra_data 'true',
        noescaping 'on'
    );
    

  3. 导入目标表。

    1
    CREATE TABLE citizens AS  SELECT * FROM gb18030_import;
    

  4. 验证数据。

    1
    SELECT count(*) FROM citizens;SELECT * FROM citizens WHERE full_name LIKE '%䶮%';
    

  5. 导出数据。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    CREATE FOREIGN TABLE gds_out
    (
        a int not null,
        b text;
        c text;
    )SERVER gsmpp_server
        OPTIONS(location 'gsfs://ip:port',
        format 'text',
        delimiter ',',
        compatible_illegal_chars 'True',
        REPLACE_ILLEGAL_CHARS ' '
    ) WRITE ONLY;
    INSERT INTO gds_out SELECT * FROM t1 ORDER BY a;
    

字符编码相关函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
-- 二进制转文本
SELECT convert_from('\x8149', 'GB18030') AS chinese_char; -- 输出:'両'

-- 文本转二进制
SELECT convert_to('华为', 'GB18030') AS byte_stream; -- 输出:\xBBAACC

-- 编码间转换
SELECT convert('\x8149', 'GB18030', 'UTF8') AS utf8_bytes;

-- 获取字符数(非字节数)
SELECT char_length('中文䶮'); -- 返回3(3个字符)

-- 按字符截取
SELECT substring('中国䶮云南', 3, 2); -- 返回'䶮云'

-- 四字节字符处理
SELECT overlay('ABCDEF' 
               PLACING '䶮' 
               FROM 3 FOR 2); -- 返回'AB䶮EF'

常见问题

  • 如何检查数据库当前字符集?
    -- 查看数据库编码
    SELECT datname, pg_encoding_to_char(encoding) 
    FROM pg_database;
    SHOW service_encoding;
    
    -- 查看客户端编码
    SHOW client_encoding;
  • 插入时遇到"invalid byte sequence"错误?

    该字符的码位不支持。

相关文档