这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

使用 Flex 表解析器

您可以使用解析器支持的选项,借助多个解析器之一加载 Flex 表。

除了本节列出的解析器之外,数据加载数据格式 中描述的以下解析器也支持 Flex 表:

1 - 使用 Flex 解析器加载列式表

您可以使用任何 Flex 解析器将数据加载到列式表中。使用 Flex 表解析器加载列式表使您能够在一个表中混合数据加载。例如,您可以将 JSON 数据加载到一个会话中,而将分隔数据加载到另一个会话中。

下面的基本示例说明了您可以如何将 Flex 解析器用于列式表。

  1. 创建一个列式表 super,其具有两列,分别是 agename

    => CREATE TABLE super(age INT, name VARCHAR);
    CREATE TABLE
    
  2. 使用 fjsonparser() 输入来自 STDIN 的 JSON 值。

    => COPY super FROM stdin PARSER fjsonparser();
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> {"age": 5, "name": "Tim"}
    >>  {"age": 3}
    >>  {"name": "Fred"}
    >>  {"name": "Bob", "age": 10}
    >> \.
    
  3. 查询该表以查看您输入的值:

    
    => SELECT * FROM super;
     age | name
    -----+------
         | Fred
      10 | Bob
       5 | Tim
       3 |
    (4 rows)
    
  4. 使用 fdelimitedparser() 输入来自 STDIN 的一些分隔值:

    => COPY super FROM stdin PARSER fdelimitedparser();
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> name |age
    >> Tim|50
    >> |30
    >> Fred|
    >> Bob|100
    >> \.
    
  5. 查询 Flex 表。JSON 和分隔数据均保存在同一个列式表 super 中。

    => SELECT * FROM super;
     age | name
    -----+------
      50 | Tim
      30 |
       3 |
       5 | Tim
     100 | Bob
         | Fred
      10 | Bob
         | Fred
    (8 rows)
    

使用 reject_on_materialized_type_error 参数避免加载类型不匹配的数据。如果 reject_on_materialized_type_error 设置为 false,Flex 解析器将接受类型不匹配的数据。请考虑以下示例:

假定待加载的 CSV 文件具有以下示例内容:

$ cat json.dat
{"created_by":"system","site_source":"flipkart_india_kol","updated_by":"system1","invoice_id":"INVDPKOL100",
"vendor_id":"VEN15731","total_quantity":12,"created_at":"2012-01-09 23:15:52.0"}
{"created_by":"system","site_source":"flipkart_india_kol","updated_by":"system2","invoice_id":"INVDPKOL101",
"vendor_id":"VEN15732","total_quantity":14,"created_at":"hello"}
  1. 创建列式表。

    => CREATE TABLE hdfs_test (
    site_source VARCHAR(200),
    total_quantity int ,
    vendor_id varchar(200),
    invoice_id varchar(200),
    updated_by varchar(200),
    created_by varchar(200),
    created_at timestamp
    );
    
  2. 加载 JSON 数据。

    =>COPY hdfs_test FROM '/home/dbadmin/json.dat' PARSER fjsonparser() ABORT ON ERROR;
    Rows Loaded
    -------------
    2
    (1 row)
    
  3. 查看内容。

    => SELECT * FROM hdfs_test;
    site_source | total_quantity | vendor_id | invoice_id | updated_by | created_by | created_at
    --------------------+----------------+-----------+-------------+------------+------------+---------------------
    flipkart_india_kol | 12 | VEN15731 | INVDPKOL100 | system1 | system | 2012-01-09 23:15:52
    flipkart_india_kol | 14 | VEN15732 | INVDPKOL101 | system2 | system |
    (2 rows)
    
  4. 如果 reject_on_materialized_type_error 参数设置为 true,您将在加载示例 JSON 数据时收到错误消息。

    => COPY hdfs_test FROM '/home/dbadmin/data/flex/json.dat' PARSER fjsonparser(reject_on_materialized_type_error=true) ABORT ON ERROR;
    ERROR 2035:  COPY: Input record 2 has been rejected (Rejected by user-defined parser)
    

2 - 加载 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

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

3 - 加载分隔的数据

您可以使用两种分隔解析器(fdelimitedparserfdelimitedpairparser)之一加载 Flex 表。

  • 数据通过各行的数据指定列名称时,使用 fdelimitedpairparser

  • 数据不指定列名称或具有与列名称对应的标题行时,使用 fdelimitedparser

本节将介绍如何使用 fdelimitedpairparser 和 fdelimitedparser 支持的一些选项。

拒绝重复值

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

=> CREATE FLEX TABLE delim_dupes();
CREATE TABLE
=> COPY delim_dupes FROM stdin PARSER fdelimitedparser(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.

拒绝实体化列类型错误

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

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

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

假定 Flex 表具有实体化的列 OwnerPercent,声明为 FLOAT。试图加载带 OwnerPercent 键(值为 VARCHAR)的行将导致 fdelimitedparser 拒绝该数据行。

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

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

    => CREATE FLEX TABLE reject_true_false(one VARCHAR, two INT);
    CREATE TABLE
    
  2. 使用 fjsonparserreject_on_materialized_type_error=false 的情况下将 JSON 数据(从 STDIN)加载至表中。尽管 false 是默认值,以下示例将显示指定该值以进行演示:

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

    =>  SELECT maptostring(__raw__), one, two FROM reject_true_false;
                   maptostring        | one | two
    ----------------------------------+-----+-----
     {
       "one" : "one",
       "two" : "2"
    }
       | one |   2
    {
       "one" : "1",
       "two" : "2"
    }
       | 1   |   2
     {
       "one" : "one",
       "two" : "two"
    }
       | one |
    (3 rows)
    
  4. 截断该表:

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

    => COPY reject_true_false FROM stdin PARSER fjsonparser(reject_on_materialized_type_error=true);
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> {"one": 1, "two": 2}
    >> {"one": "one", "two": "two"}
    >> {"one": "one", "two": 2}
    >> \.
    
  6. 调用 maptostring 显示表内容。仅加载两行,而之前的结果中有三行:

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