更新时间:2025-05-29 GMT+08:00

仅支持TEXT格式的导入导出场景

TEXT格式通过行结束符(EOL)将整个文件划分为一个个记录,再通过分隔符(delimiter,默认值为制表符'\t')将单个记录划分为一个个字段。

GaussDB使用TEXT格式需要一些特殊逻辑,比如:

  • 遇到退格符(0x08)、换页符(0x0C)、换行符(0x0A)、回车符(0x0D)、水平制表符(0x09)、垂直制表符(0x0B)会分别转义为'\b'、'\f'、'\n'、'\r'、'\t'、'\v'输出。
  • 行结束符EOL在导入场景里默认为第一个识别到的'\n'、'\r'或'\r\n',在导出场景里默认为 '\n'。
  • 遇到反斜杠会转义为双反斜杠输出。
  • 遇到NULL字段值转义为'\N'输出。

GaussDB导出并导入到GaussDB场景

建议导出命令:

1
2
3
--data_source可以是一个表名称,也可以是一个select语句。
--server_encoding可以通过SHOW server_encoding获得。
COPY {data_source} TO '/path/export.txt' eol e'\n' delimiter e'\t' ENCODING '{server_encoding}';

对应导入命令:

1
2
3
--data_destination只能是一个表名称。
--file_encoding为该二进制文件导出时指定的编码格式。
COPY {data_destination} FROM '/path/export.txt' eol e'\n' delimiter e'\t' ENCODING '{file_encoding}';

示例如下:

  1. 数据准备。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    gaussdb=# CREATE DATABASE db1 ENCODING='UTF-8' LC_COLLATE='en_US.UTF-8' LC_CTYPE ='en_US.UTF-8' DBCOMPATIBILITY = 'ORA';
    CREATE DATABASE
    
    gaussdb=# \c db1
    Non-SSL connection (SSL connection is recommended when requiring high-security)
    You are now connected to database "db1" as user "omm".
    
    db1=# create table test_copy(id int, name text);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'id' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE
    
    db1=# INSERT INTO test_copy VALUES(1, 'aaa');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(3, e'cc\tc');
    INSERT 0 1
    db1=# INSERT INTO test_copy(name) VALUES('ddd');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(5, e'ee\\e');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(6, e',');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(7, e'"');
    INSERT 0 1
    
    db1=# SELECT * FROM test_copy;
     id |   name    
    ----+-----------
      1 | aaa
      3 | cc      c
        | ddd
      5 | ee\e
      6 | ,
      7 | "
    (6 rows)
    

  2. 数据导出。

    1
    2
    db1=# COPY test_copy TO '/home/xy/test.txt' EOL e'\n' DELIMITER e'\t' ENCODING 'UTF-8';
    COPY 6
    

  3. 数据导入。

    db1=# TRUNCATE test_copy;
    TRUNCATE TABLE
    db1=# COPY test_copy FROM '/home/xy/test.txt' EOL e'\n' DELIMITER e'\t' ENCODING 'UTF-8';
    COPY 6

GaussDB导出之后自行解析数据文件的场景

该场景下一般不希望导出的TEXT文件中有GaussDB独有的转义行为,此时需要按如下方式进行处理:

  • 首先确认字段数据中是否存在行结束符或分隔符;
  • 如果包含,需要使用EOL或delimiter参数改用其他字符。需要确保指定的新EOL或delimiter不会在字段数据中存在,建议从不可见字符(0x01 ~ 0x1F)中选取;
  • 可以通过NULL选项指定对数据中的NULL值在导出时的表示方法。
  • 最后添加without escaping参数,禁止转义输出。

导出命令:

1
2
3
--data_source可以是一个表名称,也可以是一个SELECT语句
--server_encoding可以通过SHOW server_encoding获得
COPY {data_source} TO '/path/export.txt' WITHOUT escaping COL e'\x1E' DELIMITER e'\x1F' NULL '\N' ENCODING '{server_encoding}';

转义机制的核心作用是防止数据字段中的特殊字符(如分隔符、换行符)破坏文件结构。当选择禁用转义功能时,必须遵循特殊字符隔离原则:用户需谨慎选取非转义场景下的分隔符与换行符,并严格确保这些控制字符在数据内容中完全不存在。这是实现无转义文件解析的必要条件,任何字符冲突都会导致数据解析失效或结构错乱。

示例如下:

  1. 数据准备。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    gaussdb=# CREATE DATABASE db1 encoding='UTF-8' LC_COLLATE='en_US.UTF-8' LC_CTYPE ='en_US.UTF-8' dbcompatibility = 'ORA';
    CREATE DATABASE
    
    gaussdb=# \c db1
    Non-SSL connection (SSL connection is recommended when requiring high-security)
    You are now connected to database "db1" as user "omm".
    
    db1=# CREATE TABLE test_copy(id int, name text);
    NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'id' as the distribution column by default.
    HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
    CREATE TABLE
    
    db1=# INSERT INTO test_copy VALUES(1, 'aaa');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(3, e'cc\tc');
    INSERT 0 1
    db1=# INSERT INTO test_copy(name) VALUES('ddd');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(5, e'ee\\e');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(6, e',');
    INSERT 0 1
    db1=# INSERT INTO test_copy VALUES(7, e'"');
    INSERT 0 1
    
    db1=# SELECT * FROM test_copy;
     id |   name    
    ----+-----------
      1 | aaa
      3 | cc      c
        | ddd
      5 | ee\e
      6 | ,
      7 | "
    (6 rows)
    

  2. 数据导出。

    1
    2
    db1=# COPY test_copy TO '/home/xy/test.txt' WITHOUT ESCAPING EOL e'\x1E' DELIMITER e'\x1F' NULL '\N' ENCODING 'UTF-8';
    COPY 6
    

  3. 数据读取:读取文件按照选定的行结束符0x1E进行行数据的拆分,并使用分隔符0x1F将一行数据流拆分后即可获得每一行的各个字段值。

自主构造数据文件导入GaussDB的场景

当用户仅拥有字段数据,却没有完整的数据文件时,需要自行构造数据文件。若希望确保字段内容不会出现大量诸如转义、特殊字符处理等改变,推荐采用TEXT格式。当用户进行构建TEXT格式的数据文件时,需自行选定分隔符以及行结束符(EOL),以此完成数据文件的构造,进而实现数据导入。

  1. 选取行结束符:如果字段数据中存在0x0A,此时不能再使用0x0A作为行结束符,否则字段数据中的换行符会被当做行结束符,导致单行数据被一分为二。此时可以使用字段数据中不存在的字符作为行结束符,建议从不可见字符(0x01 ~ 0x1F)中选取。假设数据中未出现0x1E字符,此时我们选取0x1E作为行结束符。
  2. 选取分隔符:如果字段数据中存在制表符,此时不能再使用制表符作为分隔符,否则字段数据中的制表符被当做分隔符,导致字段被一分为二。此时可以使用字段数据中不存在的字符作为分隔符,建议从不可见字符(0x01 ~ 0x1F)中选取。假设数据中未出现0x1F字符,此时我们选取0x1F作为分隔符。
  3. 构造数据:使用选定步骤1与步骤2选定好的行结束符与分隔符组装数据文件。注意查看服务端的字符集,需要生成与服务端字符集一致的数据文件。
  4. 导入数据:示例假定当前数据文件字符集为UTF-8。

    1
    2
    db1=# COPY test_copy TO '/home/xy/test.txt' WITHOUT ESCAPING EOL e'\x1E' DELIMITER e'\x1F' NULL '\N' ENCODING 'UTF-8';
    COPY 6