数据类型
Inceptor对原生数据类别(primitive data type)和复杂数据类别(complex data type)都支持。
原生数据类别
| 数据类型 |
描述 |
示例 |
| TINYINT |
1字节(8位)有符号整数,从-128到127
| 1 |
| SMALLINT |
2字节(16位)有符号整数,从-32768到32767 |
1 |
| INT |
4字节(32位)有符号整数,从-2147483648到2147483647 |
1 |
| BIGINT |
8字节(64位)有符号整数,从-9223372036854775808到9223372036854775807 |
1 |
| FLOAT |
4字节单精度浮点数 |
1.0 |
| DOUBLE |
8字节双精度浮点数 |
1.0 |
| DECIMAL |
不可变的,任意精度的,有符号的十进制数 |
1.012,1e+44 |
| BOOLEAN |
true/false |
TRUE |
| STRING |
字符串 |
'a', ''a'' |
| VARCHAR |
可变长度的字符 |
'a', 'a ' |
| DATE |
日期。格式:'YYYY-MM-DD', 从'0001-01-01'到'9999-12-31' |
'2014-01-01' |
| TIMESTAMP | 时间戳,表示日期和时间。格式:'YYYY-MM-DD HH:MM:SS.fffffffff' ,可达到小数点后9位(纳秒级别)精度 |
'2014-01-01 00:00:00' |
| INTERVAL DAY/MONTH/YEAR | 用于存储一段以年,月或日为单位的时间 | INTERVAL '10' day |
说明
DECIMAL
DECIMAL类型让用户可以自定义数据的精度。一个DECIMAL由一个任意精度的整数未标度(unscaled value)和一个32位的整数标度(scale)组成。DECIMAL表示的数值是 unscaledValue × 10-scale。也就是说,如果标度是正数,DECIMAL数值是unscaledValue小数点左移scale位;如果标度是负数,DECIMAL数值是unscaledValue后加scale个0;如果标度是0,DECIMAL的值就是unscaledValue。DECIMAL可以用于所有常见运算(如+, -, *, /)和相应的UDF(如Floor, Ceil, Round,等等)。用户也可以用数值型(numeric type)的常见方法来在DECIMAL和别的数值型之间转换。
VARCHAR
VARCHAR生成时会带有一个长度指定数(length specifier)(1和65355之间),用来定义字符串中的最大字符数。如果一个向VARCHAR转换的STRING型中的字符个数超过了长度指定数,那么这个STRING会被自动缩短。和STRING类型一样, VARCHAR末尾的空格数是有意义的,会影响比较结果。
DATE
DATE类型只能和DATE, TIMESTAMP和STRING互显性转换(cast)。具体如下表:
| 有效显性转换 |
转换结果 |
cast(date as date) |
相同DATE值 |
cast(timestamp as date) |
根据本地时区从TIMESTAMP得出年/月/日,将其作为DATE值返回 |
cast(string as date) |
如果字符串的形式是'YYYY-MM-DD', 将对应年/月/日作为DATE值返回。如果字符串不具有这种形式,返回NULL。 |
cast(date as timestamp) |
根据本地时区生成并返回对应DATE值年/月/日零点的TIMESTAMP值。 |
cast(date as string) |
根据DATE的年/月/日值生成并返回'YYYY-MM-DD'格式的字符串。 |
TIMESTAMP
支持传统的UNIX TIMESTAMP,提供达到纳秒级别精度的选择。TIMESTAMP是以和UNIX epoch (协调世界时1970年1月1日00:00:00)之间的秒数差定义的。可以向TIMESTAMP隐性转换的数类型有:
- 整数数值型:当作UNIX TIMESTAMP秒数处理。
- 浮点数数值型:当作有小数点后精度的UNIX TIMESTAMP处理。
- 字符串:必须具有"YYYY-MM-DD HH:MM:SS[.fffffffff]"格式。小数点后秒数精度可选。
Inceptor提供了在时区间转换的UDF:to_utc_timestamp, from_utc_time。所有现成的日期时间UDF(month, day, year, hour等)都可以用于TIMESTAMP。在文本文件中,TIMESTAMP的格式必须是YYYY-MM-DD HH:MM:SS[.fffffffff]格式。如果是以其他格式表示的,先用合适的数据类型(INT,FLOAT,STRING 等)声明然后再用UDF转换成TIMESTAMP。
INTERVAL
在Inceptor中,INTERVAL类型可以分别表示以年、月、日为单位的一段时间。INTERVAL类型的数据只能和DATE类型相加,得到一个新的DATE类型。
INTERVAL 'n' DAY //长度为n天的一段时间
INTERVAL 'n' MONTH //长度为n月的一段时间
INTERVAL 'n' YEAR //长度为n年的一段时间
以下三条计算都能得到一年以后的日期:
cast('1998-08-04' AS DATE) + INTERVAL '365' DAY
cast('1998-08-04' AS DATE) + INTERVAL '1' YEAR
cast('1998-08-04' AS DATE) + INTERVAL '12' MONTH
原生数据之间的隐性转换(conversion)
Inceptor原生数据之间的隐性转换遵从下面的金字塔结构。类型可以在这个金字塔中从上向下隐性转换。但是不能由下向上隐性转换。如果需要从下向上转换,必须使用显性转换(cast)。注意,FLOAT可以隐性转换成DOUBLE,而BOOLEAN不能和任何类型之间进行转换。
复杂数据类别
| 数据类型 |
描述 |
示例 |
| ARRAY |
一组有序字段,所有字段的数据类型必须相同 |
array(1,2) |
| MAP |
一组无序的键/值对。键的类型必须是原生数据类型,值的类型可以是原生或复杂数据类型。同一个MAP的键的类型必须相同,值的类型也必须相同。 |
map('a', 1, 'b', 2) |
| STRUCT |
一组命名的字段,字段的数据类型可以不同 |
struct('a', 1, 1.0) |
| UNIONTYPE |
由一组命名的字段组成,字段的数据类型可以不同,但是一个UNIONTYPE同时只能被赋予其中一种数据类型。 |
见下 |
CREATE TABLE union_test(foo UNIONTYPE<int, double, array<string>, struct<a:int,b:string>>);
SELECT foo FROM union_test;
{0:1}
{1:2.0}
{2:["three","four"]}
{3:{"a":5,"b":"five"}}
{2:["six","seven"]}
{3:{"a":8,"b":"eight"}}
{0:9}
{1:10.0}
去序列化的UNIONTYPE的第一部份(冒号前面的部分)是一个标签(tag),用于表示被使用的字段。0表示第一个字段的数据类型(本例为INT),1表示第二个字段的数据类型(本例为DOUBLE),等等。UNIONTYPE用create_union这个UDF来创建,在创建时,必须要向create_union提供标签:
SELECT create_union(0, key), create_union(if(key<100, 0, 1), 2.0, value), create_union(1, "a", struct(2, "b")) FROM src LIMIT 2;
{0:"238"} {1:"val_238"} {1:{"col1":2,"col2":"b"}}
{0:"86"} {0:2.0} {1:{"col1":2,"col2":"b"}}