分隔数据
如果您未指定其他解析器,则 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 选项指定自定义值,请确保输入文件与该值匹配,否则可能会得到不一致的数据加载。
注意
记录终止符不能与 DELIMITER、NULL、ESCAPE 或 ENCLOSED BY 相同。使用 JDBC 时,Vertica 建议将以下值用于 RECORD TERMINATOR:
System.getProperty("line.separator")