数据类型强制转换

Vertica 支持两种数据类型转换:

  • 隐式转换:表达式自动将数据从一种类型转化成另一种类型。

  • 显式转换:SQL 语句指定转换的目标数据类型。

隐式转换

ANSI SQL-92 标准支持相似数据类型间的隐式转换:****

  • 数字类型

  • CHAR、VARCHAR、LONG VARCHAR

  • BINARY、VARBINARY、LONG VARBINARY

Vertica 支持两种类型的标量类型的非标准隐式转换:

  • 从 CHAR 到 FLOAT,以匹配从 VARCHAR 到 FLOAT 的值。以下示例将 CHAR '3' 隐式转换为 FLOAT,这样可以与第二个表达的数值 4.33 相加得到 FLOAT 类型结果。

    => SELECT '3'::CHAR + 4.33::FLOAT;
     ?column?
    ----------
       7.33
    (1 row)
    
  • DATE 与 TIMESTAMP 之间的转换。以下示例将 DATE 转换为 TIMESTAMP,计算早于上午 12 点 6 时 6 分 6 秒的时间:

    => SELECT DATE('now') - INTERVAL '6:6:6';
          ?column?
    ---------------------
     2013-07-30 17:53:54
    (1 row)
    

当表达式值的数据类型明确时,会隐式地强制转换,与预期数据类型相匹配。在以下语句中,带引号的字符串常数 '2’ 会隐式地强制转换为 INTEGER 值,使其可作为算术运算符的操作数(加法):

=> SELECT 2 + '2';
 ?column?
----------
        4
(1 row)

串联运算显式地使用任何数据类型的实参。在以下示例中,串联运算隐式地将算术表达式 2 + 2 和 INTEGER 常数 2 强制转换为 VARCHAR 值,使其可以串联起来。

=> SELECT 2 + 2 || 2;
 ?column?
----------
 42
(1 row)

另一个示例是首先获取今天的日期:

=> SELECT DATE 'now';
  ?column?
------------
 2013-07-31
(1 row)

以下命令将 DATE 转换为 TIMESTAMP,并使用 INTERVAL 在结果中添加一天半:

=> SELECT DATE 'now' + INTERVAL '1 12:00:00';
      ?column?
---------------------
 2013-07-31 12:00:00
(1 row)

大多数隐式转换保留在相关系列中,由粗略到详细朝一个方向进行。例如:

  • DATE 到 TIMESTAMP/TZ

  • INTEGER 到 NUMERIC 再到 FLOAT

  • CHAR 到 FLOAT

  • CHAR 到 VARCHAR

  • CHAR 和/或 VARCHAR 到 FLOAT

  • CHAR 到 LONG VARCHAR

  • VARCHAR 到 LONG VARCHAR

  • BINARY 到 VARBINARY

  • BINARY 到 LONG VARBINARY

  • VARBINARY 到 LONG VARBINARY

更确切地说,数据类型强制转换以此方式在 Vertica 中进行:

没有其他类型转换为或转换自 LONGVARBINARY、VARBINARY 或 BINARY。在以下列表中,<any> 表示这些类型中的一种:INT8、FLOAT8、DATE、TIME、TIMETZ、TIMESTAMP、TIMESTAMPTZ、INTERVAL。

  • <any> -> VARCHAR 为隐式

  • VARCHAR -> <any> 为显式,但 VARCHAR->FLOAT 为隐式

  • <any> <-> CHAR 为显式

  • DATE -> TIMESTAMP/TZ 为隐式

  • TIMESTAMP/TZ -> DATE 为显式,丢失时间

  • TIME -> TIMETZ 为隐式,添加本地时区

  • TIMETZ -> TIME 为显式,丢失时区

  • TIME -> INTERVAL 为隐式,day to second with days=0

  • INTERVAL -> TIME 为显式,截断非时部分

  • TIMESTAMP <-> TIMESTAMPTZ为隐式,调整为本地时区

  • TIMESTAMP/TZ -> TIME 为显式,截断非时部分

  • TIMESTAMPTZ -> TIMETZ 为显式

  • VARBINARY -> LONG VARBINARY 为隐式

  • LONG VARBINARY -> VARBINARY 为显式

  • VARCHAR -> LONG VARCHAR 为隐式

  • LONG VARCHAR -> VARCHAR 为显式

字符串到数字的数据类型转换针对科学记数法、二进制记数法、十六进制和数字型字面量组合,接受带引号常数的格式:

  • 科学记数法:

    => SELECT FLOAT '1e10';
      ?column?
    -------------
     10000000000
    (1 row)
    
  • BINARY 缩放:

    => SELECT NUMERIC '1p10';
     ?column?
    ----------
         1024
    (1 row)
    
  • 十六进制:

    => SELECT NUMERIC '0x0abc';
     ?column?
    ----------
         2748
    (1 row)
    

复杂类型

集合(arrayssets)可以隐式和显式转换。转换集合时,将转换集合的每个元素。例如,您可以将 ARRAY[VARCHAR] 转换为 ARRAY[INT],也可以将 SET[DATE] 转换为 SET[TIMESTAMPTZ]。您可以在数组和集合之间进行转换。

当强制转换为有界原生数组时,会截断过长的输入。当转换为非原生数组(即:包含复杂数据类型的数组,其中包括其他数组)时,如果新边界对于数据而言太小,则转换失败

(结构)既可以隐式转换,也可以显式转换。转换 ROW 时,将转换每个字段值。您可以在转换中指定新字段名称,或仅指定字段类型以使用现有字段名称。

转换可以增加列所需的存储空间。例如,如果将 INT 数组转换为 VARCHAR(50) 数组,则每个元素将占用更多空间,从而导致数组占用更多空间。如果差异非常大或数组有很多元素,这可能意味着数组无法再适合为该列分配的空间。在这种情况下,操作会报告错误并失败。

示例

以下示例将三个字符串转换为 NUMERIC:

=> SELECT NUMERIC '12.3e3', '12.3p10'::NUMERIC, CAST('0x12.3p-10e3' AS NUMERIC);
 ?column? | ?column? |     ?column?
----------+----------+-------------------
    12300 |  12595.2 | 17.76123046875000
(1 row)

以下示例将 VARBINARY 字符串转换为 LONG VARBINARY 数据类型:

=> SELECT B'101111000'::LONG VARBINARY;
 ?column?
----------
 \001x
(1 row)

以下示例将 CHAR 与 LONG VARCHAR 串联,得到 LONG VARCHAR:

=> \set s ''''`cat longfile.txt`''''
=> SELECT length ('a' || :s ::LONG VARCHAR);
 length
----------
 65002
(1 row)

以下示例将 NUMERIC 与 INTEGER 的数据组合转换为 NUMERIC 结果。

=> SELECT (18. + 3./16)/1024*1000;
                ?column?
-----------------------------------------
 17.761230468750000000000000000000000000
(1 row)

另请参阅