标准 SQL 中的数据类型

BigQuery 不但支持简单的数据类型(如整数),还支持更为复杂的类型(如 ARRAY 和 STRUCT)。本页面简要介绍了各种数据类型,包括允许使用的值。如需了解数据类型字面量和构造函数,请参阅词法结构和语法

数据类型属性

在存储和查询数据时,记住以下数据类型属性会很有帮助:

属性 说明 应用对象
可以为 Null NULL 是一个有效值。 所有数据类型,但存在以下例外情况:
  • ARRAY 不能为 NULL
  • NULL ARRAY 元素不能保存到表中。
可排序 可在 ORDER BY 子句中使用。 除以下类型之外的其他所有数据类型:
  • ARRAY
  • STRUCT
  • GEOGRAPHY
可分组 一般可以出现在表达式的
GROUP BYDISTINCTPARTITION BY 后面。
但是,PARTITION BY 表达式不能包含
浮点类型
除以下类型之外的其他所有数据类型:
  • ARRAY
  • STRUCT
  • GEOGRAPHY
可比较 相同类型的值可以相互比较。 所有数据类型,但存在以下例外情况:不支持 ARRAY 比较。

系统支持按字段顺序对 STRUCT 进行逐个字段的相等性比较。 字段名称会被忽略。不支持小于和大于比较。

不支持 GEOGRAPHY 比较。要比较 GEOGRAPHY 值,请使用 ST_Equals

所有支持比较的类型均可用于 JOIN 条件。如需了解联接条件的说明,请参阅 JOIN 类型

数组类型

名称 说明
ARRAY 任何非 ARRAY 类型的零个或零个以上元素的有序列表。

ARRAY 是一个包含零个或零个以上非 ARRAY 值元素的有序列表。不允许使用由 ARRAY 组成的 ARRAY。如果查询会产生由 ARRAY 组成的 ARRAY,则会返回错误。正确的做法是,您必须使用 SELECT AS STRUCT 结构在 ARRAY 之间插入 STRUCT。

目前,BigQuery 在 NULL 和 ARRAY 方面有以下两项限制:

  • 如果查询结果具有包含 NULL 元素的 ARRAY,那么尽管可以在查询中使用这些 ARRAY,BigQuery 仍会引发错误。
  • 尽管在查询中 NULL ARRAY 和空 ARRAY 是两个不同的值,但 BigQuery 会在查询结果中将 NULL ARRAY 转换为空 ARRAY。

声明 ARRAY 类型

ARRAY<T>

您可以使用尖括号(<>)来声明 ARRAY 类型。ARRAY 的元素可以是任意复杂类型,但 ARRAY 不能直接包含另一个 ARRAY。

示例

类型声明 含义
ARRAY<INT64> 由 64 位整数组成的简单 ARRAY 类型。
ARRAY<STRUCT<INT64, INT64>> 由 STRUCT 组成的 ARRAY 类型,其中每个 STRUCT 包含两个 64 位整数。
ARRAY<ARRAY<INT64>>
(不受支持)
这是一个无效的类型声明,列于此处的目的在于防止您来此查找创建多层 ARRAY 的相关信息。ARRAY 不能直接包含 ARRAY。请参阅下一个示例。
ARRAY<STRUCT<ARRAY<INT64>>> 由 64 位整数 ARRAY 组成的 ARRAY 类型。请注意,两个 ARRAY 之间存在 STRUCT,因为 ARRAY 不能直接包含其他 ARRAY。

布尔值类型

名称 说明
BOOL 布尔值由关键字 TRUEFALSE(不区分大小写)表示。

布尔值会按以下顺序排序(从最小值到最大值):

  1. NULL
  2. FALSE
  3. TRUE

字节类型

名称 说明
BYTES 长度可变的二进制数据。

STRING 和 BYTES 是不能互换使用的独立类型。STRING 的大多数函数在 BYTES 中也存在定义,但 BYTES 的那些函数会针对原始字节(而非 Unicode 字符)进行运算。STRING 和 BYTES 之间的类型转换会强制使用 UTF-8 对字节进行编码。

日期类型

名称 范围
DATE 0001-01-01 至 9999-12-31。

DATE 类型表示与时区无关的逻辑日历日期。DATE 值不代表特定的 24 小时时间段。给定的 DATE 值在不同时区下表示不同的 24 小时时间段,并且可能代表夏令时转换期间较短或较长的一天。 如需表示绝对的时间点,请使用时间戳

标准格式
'YYYY-[M]M-[D]D'
  • YYYY:以四位数字表示的年份
  • [M]M:以一位或两位数字表示的月份
  • [D]D:以一位或两位数字表示的日期

日期时间类型

名称 范围
DATETIME 0001-01-01 00:00:00 至 9999-12-31 23:59:59.999999

DATETIME 对象按照日历或时钟上的显示方式来表示日期和时间,与时区无关。 该对象包含年、月、日、小时、分钟、秒和亚秒部分。 如需表示绝对的时间点,请使用时间戳

标准格式
YYYY-[M]M-[D]D[( |T)[H]H:[M]M:[S]S[.DDDDDD]]
  • YYYY:以四位数字表示的年份
  • [M]M:以一位或两位数字表示的月份
  • [D]D:以一位或两位数字表示的日期
  • ( |T):空格或“T”分隔符
  • [H]H:以一位或两位数字表示的小时(有效值为 00 到 23)
  • [M]M:以一位或两位数字表示的分钟(有效值为 00 到 59)
  • [S]S:以一位或两位数字表示的秒钟(有效值为 00 到 59)
  • [.DDDDDD]:最多六个小数位(即高达微秒的精度)

地理位置类型

名称 说明
GEOGRAPHY 点、线和面的集合,表示为一个点集或地球表面的部分区域。

GEOGRAPHY 类型采用 OGC 简单要素规范 (SFS),是在 WGS84 参考椭球体上形成一个“简单”排列的点、线或面集合。 简单排列是指集合的多个元素不包含 WGS84 表面上任何点的排列方式。如果存在自相交,系统会自动移除它们。

GEOGRAPHY地理位置函数的结果或参数。

数值类型

数值类型包括下列类型:

  • INT64
  • NUMERIC,别名为 DECIMAL
  • BIGNUMERIC,别名为 BIGDECIMAL预览版
  • FLOAT64

整数类型

整数是指不含小数部分的数值。

姓名 范围
INT64 -9,223,372,036,854,775,808 至 9,223,372,036,854,775,807

十进制类型

十进制类型值是具有固定精度和标度的数值。精度是指数字所包含的位数。标度是指小数点后的位数。

此类型可以精确表示小数部分,适用于财务计算。

姓名 精度、标度和范围
NUMERIC
DECIMAL
精度:38
标度:9
最小值:-9.9999999999999999999999999999999999999E+28
最大值:9.9999999999999999999999999999999999999E+28
BIGNUMERIC
BIGDECIMAL
预览版
精度:76.76(第 77 位不完整)
小数位:38
最小值:-5.7896044618658097711785492504343953926634992332820282019728792003956564819968E+38
最大值:5.7896044618658097711785492504343953926634992332820282019728792003956564819967E+38

DECIMALNUMERIC 的别名。BIGDECIMALBIGNUMERIC 的别名。

浮点类型

浮点值是含有小数部分的近似数值。

姓名 说明
FLOAT64 双精度(近似)数值。

浮点语义

使用浮点数时,需要考虑特殊的非数值:NaN+/-inf

算术运算符可为产生有限输出的所有有限输入值和至少有一个非有限输入的所有运算提供标准 IEEE-754 行为。

如果输入有限,但输出非有限,则函数调用和运算符会返回溢出错误。如果输入包含非有限值,则输出可以是非有限的。一般而言,函数不会引入 NaN+/-inf。但是,像 IEEE_DIVIDE 这样的特定函数可以为有限输入返回非有限值。所有此类情况都会在数学函数中明确指出。

数学函数示例
左侧运算对象 运算符 右侧运算对象 返回值
任意值 + NaN NaN
1.0 + +inf +inf
1.0 + -inf -inf
-inf + +inf NaN
最大 FLOAT64 + 最大 FLOAT64 溢出错误
最小 FLOAT64 / 2.0 0.0
1.0 / 0.0 “除以零”错误

比较运算符为浮点输入提供标准的 IEEE-754 行为。

比较运算符示例
左侧运算对象 运算符 右侧运算对象 返回值
NaN = 任意值 FALSE
NaN < 任意值 FALSE
任意值 < NaN FALSE
-0.0 = 0.0 TRUE
-0.0 < 0.0 FALSE

浮点值会按以下顺序排序(从最小值到最大值):

  1. NULL
  2. NaN - 排序时,所有 NaN 值都会被视为相等。
  3. -inf
  4. 负数
  5. 0 或 -0 - 排序时,所有零值被视为相等。
  6. 正数
  7. +inf

特殊浮点值按以下方式分组,包括由 GROUP BY 子句完成的分组和由 DISTINCT 关键字完成的分组:

  • NULL
  • NaN - 分组时,所有 NaN 值都会被视为相等。
  • -inf
  • 0 或 -0 - 分组时,所有零值被视为相等。
  • +inf

字符串类型

名称 说明
STRING 长度可变的字符 (Unicode) 数据。

输入的 STRING 值必须采用 UTF-8 编码,输出的 STRING 值同样采用 UTF-8 编码。CESU-8 和经过修改的 UTF-8 等替代编码被视为无效的 UTF-8 编码。

所有作用于 STRING 值的函数和运算符都会对 Unicode 字符(而非字节)进行运算。例如,应用于 STRING 输入的函数(如 SUBSTRLENGTH)计算的是字符数,而非字节数。

每个 Unicode 字符都有一个分配给它的称为代码点的数值。 较低的代码点分配给较低位的字符。比较字符时,代码点决定了哪些字符小于或大于其他字符。

STRING 的大多数函数在 BYTES 中也存在定义,但 BYTES 的那些函数会针对原始字节(而非 Unicode 字符)进行运算。STRING 和 BYTES 是不能互换使用的独立类型。任何方向都不存在隐式类型转换。STRING 和 BYTES 之间的显式类型转换采用 UTF-8 编码和解码。如果字节不是有效的 UTF-8 编码,则将 BYTES 转换为 STRING 时会返回错误。

结构体类型

名称 说明
STRUCT 有序字段的容器,其中每个字段都有一个类型(必需)和字段名称(可选)。

声明 STRUCT 类型

STRUCT<T>

您可以使用尖括号(<>)来声明 STRUCT 类型。STRUCT 的元素可以是任意复杂类型。

示例

类型声明 含义
STRUCT<INT64> 具有单个未命名 64 位整数字段的简单 STRUCT 类型。
STRUCT<x STRUCT<y INT64, z INT64>> 具有名为 x 的嵌套 STRUCT 的 STRUCT 类型。STRUCT x 具有 yz 两个字段,二者都是 64 位整数。
STRUCT<inner_array ARRAY<INT64>> 包含名为 inner_array 的 ARRAY 且 ARRAY 由 64 位整数元素组成的 STRUCT 类型。

构造 STRUCT

元组语法

(expr1, expr2 [, ... ])

输出类型是具有匿名字段的匿名 STRUCT 类型,其类型与输入表达式的类型相匹配。必须指定至少两个表达式。否则无法区分该语法与用圆括号括起来的表达式。

示例

语法 输出类型 说明
(x, x+y) STRUCT<?,?> 如果使用列名称(未加引号的字符串),则 STRUCT 字段数据类型由列数据类型派生而来。xy 是列,因此 STRUCT 字段的数据类型由列类型和加法运算符的输出类型派生而来。

对于使用多部分键的比较表达式,此语法还可与 STRUCT 比较搭配使用,例如,在 WHERE 子句中:

WHERE (Key1,Key2) IN ( (12,34), (56,78) )

无类型结构体语法

STRUCT( expr1 [AS field_name] [, ... ])

允许使用重复的字段名称。没有名称的字段会被视为匿名字段,不能通过名称进行引用。STRUCT 的值可以为 NULL,也可以拥有 NULL 字段值。

示例

语法 输出类型
STRUCT(1,2,3) STRUCT<int64,int64,int64>
STRUCT() STRUCT<>
STRUCT('abc') STRUCT<string>
STRUCT(1, t.str_col) STRUCT<int64, str_col string>
STRUCT(1 AS a, 'abc' AS b) STRUCT<a int64, b string>
STRUCT(str_col AS abc) STRUCT<abc string>

类型化结构体语法

STRUCT<[field_name] field_type, ...>( expr1 [, ... ])

类型化语法允许使用显式 STRUCT 数据类型来构造 STRUCT。输出类型与提供的 field_type 类型完全一致。如果两种类型不相同,则输入表达式会被强制转换为 field_type 指定的类型;如果类型不兼容,则会产生错误。输入表达式不允许使用 AS alias。表达式的数量必须与类型中的字段数相匹配,并且表达式类型必须可强制转换或字面上强制转换为字段类型。

示例

语法 输出类型
STRUCT<int64>(5) STRUCT<int64>
STRUCT<date>("2011-05-05") STRUCT<date>
STRUCT<x int64, y string>(1, t.str_col) STRUCT<x int64, y string>
STRUCT<int64>(int_col) STRUCT<int64>
STRUCT<x int64>(5 AS x) 错误 - 类型化语法不允许使用 AS

STRUCT 的有限比较

可以使用等号运算符直接比较 STRUCT:

  • 等于 (=)
  • 不等于(!=<>
  • [NOT] IN

但是请注意,这些直接相等性比较会按顺序成对比较 STRUCT 的字段,并忽略字段名称。如果您希望比较 STRUCT 的同名字段,则可直接比较个别字段。

时间类型

名称 范围
TIME 00:00:00 至 23:59:59.99999。

TIME 对象按照手表上的显示方式来表示时间,与特定日期和时区无关。 如需表示绝对的时间点,请使用时间戳

标准格式
[H]H:[M]M:[S]S[.DDDDDD]
  • [H]H:以一位或两位数字表示的小时(有效值为 00 到 23)
  • [M]M:以一位或两位数字表示的分钟(有效值为 00 到 59)
  • [S]S:以一位或两位数字表示的秒钟(有效值为 00 到 59)
  • [.DDDDDD]:最多六个小数位(即高达微秒的精度)

时间戳类型

名称 范围
TIMESTAMP 0001-01-01 00:00:00 至 9999-12-31 23:59:59.999999(世界协调时间 (UTC))

TIMESTAMP 对象表示绝对时间点,与任何时区或惯例(如夏令时)无关,可精确到微秒。

  • 如需按日历上显示的方式来表示日期,请使用 DATE 对象。
  • 如需按时钟上显示的方式来表示时间,请使用 TIME 对象。
  • 如需按日历和时钟上显示的方式来表示日期和时间,请使用 DATETIME 对象。
标准格式
YYYY-[M]M-[D]D[( |T)[H]H:[M]M:[S]S[.DDDDDD]][time zone]
  • YYYY:以四位数字表示的年份
  • [M]M:以一位或两位数字表示的月份
  • [D]D:以一位或两位数字表示的日期
  • ( |T):空格或“T”分隔符
  • [H]H:以一位或两位数字表示的小时(有效值为 00 到 23)
  • [M]M:以一位或两位数字表示的分钟(有效值为 00 到 59)
  • [S]S:以一位或两位数字表示的秒钟(有效值为 00 到 59)
  • [.DDDDDD]:最多六个小数位(即高达微秒的精度)
  • [time zone]:表示时区的字符串。 如果未明确指定时区,则使用默认时区,即世界协调时间 (UTC)。 如需了解详情,请参阅时区部分。

时区

在解析时间戳或设置其格式以用于显示时,会用到时区。时间戳值本身不会存储特定的时区,也不会在应用时区偏移时发生更改。

时区由以下任一标准格式的字符串表示:

  • 世界协调时间 (UTC) 的偏移量或代表 UTC 的字母 Z
  • tz 数据库中的时区名称

相对于世界协调时间 (UTC) 的偏移量

(+|-)H[H][:M[M]]
Z

示例

-08:00
-8:15
+3:00
+07:30
-7
Z

使用此格式时,时区和时间戳的其余部分之间不允许留有空格。

2014-09-27 12:30:00.45-8:00
2014-09-27T12:30:00.45Z

时区名称

continent/[region/]city

时区名称来自 tz 数据库。 请参阅维基百科上的 tz 数据库时区列表,其中提供了虽不全面但较为简单的参考信息。

示例

America/Los_Angeles
America/Argentina/Buenos_Aires

使用时区名称时,名称和时间戳的其余部分之间必须留有空格:

2014-09-27 12:30:00.45 America/Los_Angeles

注意:并非所有时区名称都可以互换,即使这些时区在一年当中的某些特定期间恰好报告了相同的时间。例如,在夏令时期间,America/Los_Angeles 报告的时间与 UTC-7:00 相同;但在非夏令时期间,其报告的时间与 UTC-8:00 相同。

如果未指定时区,则使用默认时区值。

闰秒

时间戳只是相对于世界协调时间 (UTC) 1970-01-01 00:00:00 的偏移量(假设每分钟正好 60 秒)。存储的时间戳不能表示闰秒。

如果输入包含在秒钟字段中使用“:60”来表示闰秒的值,则系统不会在转换为时间戳值时保留该闰秒,而是会将该值解释为下一分钟的时间戳(秒钟字段的值为“:00”)。

闰秒不会影响时间戳的计算。所有时间戳均使用 Unix 样式的时间戳进行计算,而这种样式的时间戳不能体现闰秒。闰秒只能通过测定真实世界时间的函数进行观察。在这些函数中,若存在闰秒,系统可能会跳过或重复时间戳的秒值。