分隔数据

如果您未指定其他解析器,则 Vertica 默认使用 DELIMITED 解析器。您可以在 COPY 语句中指定分隔符、转义字符、处理 null 值的方式以及其他参数。

以下示例显示分隔符为 '|' 时的默认行为

=> CREATE TABLE employees (id INT, name VARCHAR(50), department VARCHAR(50));
CREATE TABLE

=> COPY employees FROM STDIN;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 42|Sheldon Cooper|Physics
>> 17|Howard Wolowitz|Astronomy
>> \.

=> SELECT * FROM employees;
 id |      name       |  department
----+-----------------+--------------
 17 | Howard Wolowitz | Astrophysics
 42 | Sheldon Cooper  | Physics
(2 rows)

默认情况下,集合值用括号分隔,元素用逗号分隔。集合必须是一维数组或标量类型集。

=> CREATE TABLE researchers (id INT, name VARCHAR, grants ARRAY[VARCHAR], values ARRAY[INT]);
CREATE TABLE

=> COPY researchers FROM STDIN;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 42|Sheldon Cooper|[US-7376,DARPA-1567]|[65000,135000]
>> 17|Howard Wolowitz|[NASA-1683,NASA-7867,SPX-76]|[16700,85000,45000]
>> \.

=> SELECT * FROM researchers;
 id |      name       |               grants               |       values
----+-----------------+------------------------------------+---------------------
 17 | Howard Wolowitz | ["NASA-1683","NASA-7867","SPX-76"] | [16700,85000,45000]
 42 | Sheldon Cooper  | ["US-7376","DARPA-1567"]           | [65000,135000]
(2 rows)

若要将某个特殊字符用作字面量,请在其前面添加一个转义字符。例如,要在加载的数据(例如当包含文件路径时)中包含一个字面量反斜线 (\),请使用两个反斜线 (\)。COPY 会在加载转义的字符时从输入中删除转义字符。

加载分隔数据时,两个连续的分隔符表示一个 null 值,除非另外设置了 NULL 参数。最后的分隔符是可选的。例如,以下输入对上一个表有效:


=> COPY employees FROM STDIN;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 45|Raj|
>> 21|Leonard||
>> \.

=> SELECT * FROM employees;
 id |  name   |  department
----+---------+--------------
 21 | Leonard |
 42 | Raj     |
(2 rows)

默认情况下,如果数据包含的值太少,则加载失败。您可以使用 TRAILING NULLCOLS 选项接受任意数量的缺失列,并将其值视为 null。

Vertica 假设数据采用 UTF-8 编码。

特定于 DELIMITED 解析器的选项及其默认值为:

要将分隔数据加载到 Flex 表中,请使用 FDELIMITEDPARSER 解析器。

更改列分隔符 (DELIMITER)

默认 COPY 分隔符为竖线 ('|')。DELIMITER 是一个 ASCII 字符,用于分隔输入源中每条记录内的各个列。在两个分隔符之间,COPY 会将输入中的所有字符串数据解释为字符。请勿在字符串两侧加引号,因为引号字符也会被视为两个分隔符之间的字面量。

可以使用 E'\000' 至 E'\177'(包含)范围内的任何 ASCII 值来定义不同的分隔符。例如,如果加载的是 CSV 数据文件,并且这些文件使用逗号 (',') 字符作为分隔符,则可以将默认分隔符更改为逗号。不能对 DELIMITER 和 NULL 选项使用相同的字符。

如果分隔符位于一串数据值之间,请使用 ESCAPE AS 字符(默认值为 '\')来指明应将分隔符视为字面量。

COPY 语句可接受空值(即两个连续分隔符)作为 CHAR 和 VARCHAR 数据类型的有效输入数据。COPY 会将空列存储为一个空字符串 ('')。空字符串不等同于 NULL 字符串。

要指示一个不可打印的分隔符(例如 Tab 键),请采用扩展字符串语法 (E'...') 来指定该字符。如果数据库启用了 StandardConformingStrings,请使用 Unicode 字符串字面量 (U&'...')。例如,使用 E'\t' 或 U&'\0009' 将 Tab 键指定为分隔符。

以下示例将从逗号分隔文件加载数据:

=> COPY employees FROM ... DELIMITER ',';

在以下示例中,第一列具有特定于列的分隔符:

=> COPY employees(id DELIMITER ':', name, department) FROM ... DELIMITER ',';

更改集合分隔符(COLLECTIONDELIMITER、COLLECTIONOPEN、COLLECTIONCLOSE)

DELIMITER 选项可指定在输入中分隔列的值。对于具有集合类型(ARRAY 或 SET)的列,集合的各元素之间还需要一个分隔符。此外,集合本身具有开始和结束标记。默认情况下,集合会用括号括起来,元素则用逗号进行分隔,但您可以更改这些值。

在以下示例中,集合用大括号括起来且用句点进行分隔。

=> COPY researchers FROM STDIN COLLECTIONOPEN '{' COLLECTIONCLOSE '}' COLLECTIONDELIMITER '.';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 19|Leonard|{"us-1672"."darpa-1963"}|{16200.16700}
>> \.

=> SELECT * FROM researchers;
 id |      name       |               grants               |       values
----+-----------------+------------------------------------+---------------------
 17 | Howard Wolowitz | ["NASA-1683","NASA-7867","SPX-76"] | [16700,85000,45000]
 42 | Sheldon Cooper  | ["US-7376","DARPA-1567"]           | [65000,135000]
 19 | Leonard         | ["us-1672","darpa-1963"]           | [16200,16700]
(3 rows)

更改将列或集合值括起来的字符(ENCLOSED BY、COLLECTIONENCLOSE)

使用 ENCLOSED BY 参数可以设置 ASCII 字符来分隔嵌入在字符串值中的各个字符。当且仅当括号字符是输入的第一个和最后一个字符时,括号字符才不会被视为是数据的一部分。可以将 E'\001' 至 E'\177'(包含)范围内的任何 ASCII 值(除 NULL: E'\000' 以外的任何 ASCII 字符)用于 ENCLOSED BY 值。使用双引号 (") 很常见,如以下示例所示。

=> COPY employees FROM STDIN ENCLOSED BY '"';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 21|Leonard|Physics
>> 42|"Sheldon"|"Physics"
>> 17|Rajesh "Raj" K|Astronomy
>> \.

=> SELECT * FROM employees;
 id |     name       |  department
----+----------------+--------------
 17 | Rajesh "Raj" K | Astronomy
 21 | Leonard        | Physics
 42 | Sheldon        | Physics
(3 rows)

请注意,虽然 ENCLOSED BY 是双引号,但 Rajesh 姓名中嵌入的引号被视为数据的一部分,因为它们不是列中的第一个字符和最后一个字符。出于所处位置原因,已删除将 "Sheldon" 和 "Physics" 括起来的引号。

在集合值中,COLLECTIONENCLOSE 参数类似于集合中各个元素的 ENCLOSED BY。

更改 null 指示符 (NULL)

默认情况下,列值的空字符串 ('') 表示 NULL。您可以在 E'\001'E'\177'(包含)范围内指定其他 ASCII 值(除 NUL: E'\000' 之外的任何 ASCII 字符)作为 NULL 指示符。不能对 DELIMITER 和 NULL 选项使用相同的字符。

包含一个或多个空格字符的列不是 NULL,除非空格的顺序与 NULL 字符串完全匹配。

NULL 不区分大小写,但必须是数据字段分隔符之间的唯一值。例如,如果 NULL 字符串为 NULL 且分隔符为默认的竖线 (|):

|NULL| 表示 null 值。

| NULL | 不表示 null 值。

在脚本中使用 COPY 语句时,必须将包含反斜线的每个 NULL 字符串替换为双反斜线。例如,用于加载示例数据库的脚本包含:

COPY ... NULL E'\\n' ...

更改集合值的 null 指示符 (COLLECTIONNULLELEMENT)

NULL 选项指定要将列值视为 null 的值。对于具有集合类型(ARRAY 或 SET)的列,单独的选项将指定如何解释 null 元素。默认情况下,"null" 表示 null 值。表示两个连续的元素分隔符的空值表示 null:

=> COPY researchers FROM STDIN;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 17|Howard|["nasa-143",,"nasa-6262"]|[10000,1650,15367]
>> 19|Leonard|["us-177",null,"us-6327"]|[16200,64000,26500]
>> \.

=> SELECT * FROM researchers;
 id |  name   |           grants            |       values
----+---------+-----------------------------+---------------------
 17 | Howard  | ["nasa-143","","nasa-6262"] | [10000,1650,15367]
 19 | Leonard | ["us-177",null,"us-6327"]   | [16200,64000,26500]
(2 rows)

使用 COLLECTIONNULLELEMENT 指定不同的值,如以下示例所示。

=> COPY researchers from STDIN COLLECTIONNULLELEMENT 'x';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 42|Sheldon|[x,"us-1672"]|[x,165000]
>> \.

=> SELECT * FROM researchers;
 id |  name   |           grants            |       values
----+---------+-----------------------------+---------------------
 17 | Howard  | ["nasa-143","","nasa-6262"] | [10000,1650,15367]
 19 | Leonard | ["us-177",null,"us-6327"]   | [16200,64000,26500]
 42 | Sheldon | [null, "us-1672"]           | [null,165000]
(3 rows)

填充缺失的列 (TRAILING NULLCOLS)

默认情况下,如果输入不包含足够的列,则 COPY 会失败。使用 TRAILING NULLCOLS 选项为缺少数据的任何列插入 NULL 值。此选项不能用于具有 NOT NULL 约束的列。

以下示例演示了如何使用此选项。

=> CREATE TABLE z (a INT, b INT, c INT );

--- insert with enough data:
=> INSERT INTO z VALUES (1, 2, 3);

=> SELECT * FROM z;
 a | b | c
---+---+---
 1 | 2 | 3
(1 row)

--- insert deficient data:
=> COPY z FROM STDIN TRAILING NULLCOLS;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 4 | 5 | 6
>> 7 | 8
>> \.

=> SELECT * FROM z;
 a | b | c
---+---+---
 1 | 2 | 3
 4 | 5 | 6
 7 | 8 |
(3 rows)

更改转义字符(ESCAPE AS、NO ESCAPE)

您可以指定一个转义字符,它可以将任何特殊字符视为数据的一部分。例如,如果 CSV 文件中的元素应包含逗号,您可以通过在数据中的逗号前面附加转义字符来加以表示。默认转义字符为反斜线 (\)。

要将默认字符更改为其他字符,请使用 ESCAPE AS 选项。可以将转义字符设置为 E'\001'E'\177'(包含)范围内的任何 ASCII 值。

如果您不需要任何转义字符且希望阻止任何字符被解释为转义序列,请使用 NO ESCAPE 选项。

ESCAPE AS 和 NO ESCAPE 可以在列和全局级别进行设置。

更改行尾字符 (RECORD TERMINATOR)

要指定表示数据文件记录结尾的字面量字符串,请使用 RECORD TERMINATOR 参数,后跟要使用的字符串。如果不指定值,则 Vertica 会尝试确定正确的行结束符,即仅接受换行符 (E'\n')(通常在 UNIX 系统上)或接受回车键和换行符 (E'\r\n')(通常在 Windows 平台上)。

例如,如果您的文件包含以换行符终止的逗号分隔值且您希望保留换行符,请使用 RECORD TERMINATOR 选项指定替代值:

=>  COPY mytable FROM STDIN DELIMITER ',' RECORD TERMINATOR E'\n';

要将 RECORD TERMINATOR 指定为不可打印的字符,请使用扩展字符串语法或 Unicode 字符串字面量。下表列出了一些常见的记录终止符。有关字面量字符串格式的说明,请参阅字符串字面量

如果使用 RECORD TERMINATOR 选项指定自定义值,请确保输入文件与该值匹配,否则可能会得到不一致的数据加载。

使用 JDBC 时,Vertica 建议将以下值用于 RECORD TERMINATOR

System.getProperty("line.separator")