加载 CSV 数据

使用 fcsvparser 加载 CSV 格式(逗号分隔值)的数据。由于不存在正式的 CSV 标准,Vertica 支持 RFC 4180 标准为 fcsvparser 的默认行为。其他解析器参数则将 CSV 选项的各种组合简化成列式表或 Flex 表。使用 fcsvparser 解析以下 CSV 数据格式:

  • **RFC 4180:**Vertica Flex 表的 RFC4180 CSV 格式解析器。此格式的参数为固定值,无法更改。

  • 传统: 传统 CSV 解析器允许您指定参数值,如分隔符或记录终止符。有关参数的详细列表,请参阅 FCSVPARSER

使用默认解析器设置

这些固定的参数设置适用于 RCF4180 格式。

您可以对 enclosed_byescape 使用相同的值。其他值必须唯一。

使用 type 参数指示文件符合 RFC 4180 格式还是传统格式。您可以将 type 指定为 RCF4180。但您必须首先验证数据是否与前面 RFC4180 格式参数的固定值兼容。type 参数的默认值为 RFC4180.

加载 CSV 数据 (RFC4180)

请按照以下步骤,使用 fcsvparser 加载 RFC4180 CSV 数据格式的数据。

要执行此任务,假定待加载的 CSV 文件具有以下示例内容:

$ more /home/dbadmin/flex/flexData1.csv
sno,name,age,gender
1,John,14,male
2,Mary,23,female
3,Mark,35,male
  1. 创建 Flex 表:

    => CREATE FLEX TABLE csv_basic();
    CREATE TABLE
    
  2. 使用 fcsvparser 从 CSV 文件加载数据:

    => COPY csv_basic FROM '/home/dbadmin/flex/flexData1.csv' PARSER fcsvparser();
    Rows Loaded
    -------------
    3
    (1 row)
    
  3. 查看加载到 Flex 表中的数据:

    => SELECT maptostring(__raw__) FROM csv_basic;
    maptostring
    ----------------------------------------------------------------------------------
    {
    "age" : "14",
    "gender" : "male",
    "name" : "John",
    "sno" : "1"
    }
    {
    "age" : "23",
    "gender" : "female",
    "name" : "Mary",
    "sno" : "2"
    }
    {
    "age" : "35",
    "gender" : "male",
    "name" : "Mark",
    "sno" : "3"
    }
    (3 rows)
    

加载 CSV 数据(传统)

请按照以下步骤,使用 fcsvparser 加载传统 CSV 数据格式的数据。

在此示例中,CSV 文件将 $ 用作 delimiter,将 # 用作 record_terminator。待加载的示例 CSV 文件具有以下内容:

$ more /home/dbadmin/flex/flexData1.csv
sno$name$age$gender#
1$John$14$male#
2$Mary$23$female#
3$Mark$35$male#
  1. 创建 Flex 表:

    => CREATE FLEX TABLE csv_basic();
    CREATE TABLE
    
  2. 使用带有参数 type='traditional'delimiter='$'record_terminator='#'fscvparser 加载 Flex 表中的数据:

    => COPY csv_basic FROM '/home/dbadmin/flex/flexData2.csv' PARSER fcsvparser(type='traditional',
    delimiter='$', record_terminator='#');
    Rows Loaded
    -------------
    3
    (1 row)
    
  3. 查看加载到 Flex 表中的数据:

    
    => SELECT maptostring(__raw__) FROM csv_basic;
    maptostring
    ----------------------------------------------------------------------------------
    {
    "age" : "14",
    "gender" : "male",
    "name" : "John",
    "sno" : "1"
    }
    {
    "age" : "23",
    "gender" : "female",
    "name" : "Mary",
    "sno" : "2"
    }
    {
    "age" : "35",
    "gender" : "male",
    "name" : "Mark",
    "sno" : "3"
    }
    (3 rows)
    

拒绝重复值

您可以通过使用 fcsvparserreject_on_duplicate=true 选项拒绝重复值。加载在拒绝重复值后继续。下个示例演示了如何使用此参数,接着显示了指定的异常和拒绝的数据文件。将被拒绝的数据保存到表而不是文件中,包括数据及其异常。

=> CREATE FLEX TABLE csv_basic();
CREATE TABLE
=> COPY csv_basic FROM stdin PARSER fcsvparser(reject_on_duplicate=true)
exceptions '/home/dbadmin/load_errors/except.out' rejected data '/home/dbadmin/load_errors/reject.out';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> A|A
>> 1|2
>> \.
=> \! cat /home/dbadmin/load_errors/reject.out
A|A
=> \! cat /home/dbadmin/load_errors/except.out
COPY: Input record 1 has been rejected (Processed a header row with duplicate keys with
reject_on_duplicate specified; rejecting.).  Please see /home/dbadmin/load_errors/reject.out,
record 1 for the rejected record.
COPY: Loaded 0 rows, rejected 1 rows.

拒绝包含实体化列类型错误的数据

fcsvparser 解析器具有一个布尔参数 reject_on_materialized_type_error。将此参数设置为 true 将导致行被拒绝,前提是输入数据中同时存在以下情况:

  • 包括与现有实体化列匹配的键

  • 具有无法强迫采用实体化列数据类型的键值

以下示例演示了如何设置该参数。

  1. 创建一个表 reject_true_false,带有两个实际列:

    => CREATE FLEX TABLE reject_true_false(one int, two int);
    CREATE TABLE
    
  2. 使用 fcsvparserreject_on_materialized_type_error=false 的情况下将 CSV 数据加载至表(从 STDIN 中)中。虽然 false 是默认值,但您可以显式指定它,如下所示。此外,设置参数 header=true 以指定输入值对应的列:

    => COPY reject_true_false FROM stdin PARSER fcsvparser(reject_on_materialized_type_error=false,header=true);
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> one,two
    >> 1,2
    >> "3","four"
    >> "five",6
    >> 7,8
    >> \.
    
  3. 调用 maptostring 在加载数据之后显示表值:

    => SELECT maptostring(__raw__), one, two FROM reject_true_false;
    maptostring               | one | two
    ----------------------------------------+-----+-----
    {
    "one" : "1",
    "two" : "2"
    }
    |   1 |   2
    {
    "one" : "3",
    "two" : "four"
    }
    |   3 |
    {
    "one" : "five",
    "two" : "6"
    }
    |     |   6
    {
    "one" : "7",
    "two" : "8"
    }
    |   7 |   8
    (4 rows)
    
  4. 截断该表以清空表中存储的数据:

    => TRUNCATE TABLE reject_true_false;
    TRUNCATE TABLE
    
  5. 重新加载相同的数据,但这次请设置 reject_on_materialized_type_error=true

    => COPY reject_true_false FROM stdin PARSER fcsvparser(reject_on_materialized_type_error=true,header=true);
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> one,two
    >> 1,2
    >> "3","four"
    >> "five",6
    >> 7,8
    >> \.
    
  6. 调用 maptostring 显示表内容。当前仅加载两行,而之前的结果中有四行。含有数据类型不正确的输入值的行已被拒绝:

    => SELECT maptostring(__raw__), one, two FROM reject_true_false;
    maptostring             | one | two
    -------------------------------------+-----+-----
    {
    "one" : "1",
    "two" : "2"
    }
    |   1 |   2
    {
    "one" : "7",
    "two" : "8"
    }
    |   7 |   8
    (2 rows)
    

拒绝或忽略空行

有效的 CSV 文件可能包含空键值对。这些行对 SQL 无效。您可以使用两个布尔 FCSVPARSER 参数拒绝或忽略空行,从而控制其行为:

  • reject_on_empty_key
  • omit_empty_keys

下面的示例演示了如何设置这些参数:

  1. 创建 Flex 表:

     => CREATE FLEX TABLE csv_basic();
    CREATE TABLE
    
  2. 使用 fcsvparserreject_on_empty_key=false 的情况下将 CSV 数据加载至表(从 STDIN 中)中。虽然 false 是默认值,但您可以显式指定它,如下所示。此外,设置参数 header=true 以指定输入值对应的列:

    => COPY csv_basic FROM stdin PARSER fcsvparser(reject_on_empty_key=false,header=true);
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> ,num
    >> 1,2
    >> \.
    
  3. 调用 maptostring 在加载数据之后显示表值:

    =>SELECT maptostring(__raw__) FROM csv_basic;
    maptostring
    ----------------------------------
    {
    "" : "1",
    "num" : "2"
    }
    
    (1 row)
    
  4. 截断该表以清空表中存储的数据:

    => TRUNCATE TABLE csv_basic;
    TRUNCATE TABLE
    
  5. 重新加载相同的数据,但这次请设置 reject_on_empty_key=true

    => COPY csv_basic FROM stdin PARSER fcsvparser(reject_on_empty_key=true,header=true);
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> ,num
    >> 1,2
    >> \.
    
  6. 调用 maptostring 显示表内容。未加载任何行,因为其中一个键为空:

    =>SELECT maptostring(__raw__) FROM csv_basic;
    maptostring
    -------------
    (0 rows)
    
  7. 截断该表以清空表中存储的数据:

    => TRUNCATE TABLE csv_basic;
    TRUNCATE TABLE
    
  8. 重新加载相同的数据,但这次请设置 omit_empty_keys=true

    => COPY csv_basic FROM stdin PARSER fcsvparser(omit_empty_keys=true,header=true);
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> ,num
    >> 1,2
    >> \.
    
  9. 调用 maptostring 显示表内容。现已加载一行,带空键的行已被忽略:

    => SELECT maptostring(__raw__) FROM csv_basic;
    maptostring
    ---------------------
    {
    "num" : "2"
    }
    (1 row)
    

使用 NULL 参数

使用带有 fcsvparser 的 COPY NULL 元数据参数,将 NULL 值加载到 Flex 表中。

下面的示例使用此参数:

  1. 创建 Flex 表:

    => CREATE FLEX TABLE fcsv(c1 int);
    CREATE TABLE
    
  2. 使用 STDIN 和 NULL 参数将 CSV 数据加载到 Flex 表中:

    => COPY fcsv FROM STDIN PARSER fcsvparser() NULL 'NULL' ;
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> a,b,c1
    >> 10,20,NULL
    >> 20,30,50
    >> 20,30,40
    >> \.
    
  3. 使用 compute_flextable_keys_and_build_view 函数计算键并构建 Flex 视图:

    => SELECT compute_flextable_keys_and_build_view('fcsv');
    compute_flextable_keys_and_build_view
    --------------------------------------------------------------------------------
    Please see public.fcsv_keys for updated keys
    The view public.fcsv_view is ready for querying
    (1 row)
    
  4. 查看 Flex 视图并替换 NULL 值:

    => SELECT * FROM public.fcsv_view;
    a  | b  | c1
    ----+----+----
    20 | 30 | 50
    10 | 20 |
    20 | 30 | 40
    (3 rows)
    
    => SELECT a,b, ISNULL(c1,-1) from public.fcsv_view;
    a  | b  | ISNULL
    ----+----+--------
    20 | 30 |     50
    10 | 20 |     -1
    20 | 30 |     40
    (3 rows)
    

处理列标题

fcsvparser 允许您使用 HEADER_NAMES= 参数指定您自己的列标题。此参数完全替换 CSV 源标题行中的列名。

例如,要将这六个列标题用于您正在加载的 CSV 文件,请使用 fcsvparser 参数,如下所示:

HEADER_NAMES='FIRST, LAST, SOCIAL_SECURITY, TOWN, STATE, COUNTRY'

如果提供比现有数据列更少的标题名称,则 fcsvparser 在您提供的名称之后使用默认名称。默认标题名称由 ucoln 组成,其中 n 是列偏移量,第一列从 0 开始。例如,如果您为 6 列表提供四个标题名称,fcsvparser 会在您提供的第四个标题名称之后提供默认名称 ucol4ucol5

如果您提供的标题多于现有表列,则任何其他标题都将保持未使用状态。