标准 SQL 数据类型

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

数据类型属性

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

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

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

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

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


数值类型

数值类型包括整数类型、浮点类型和 NUMERIC 数据类型。

整数类型

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

名称 存储空间大小 范围
INT64 8 个字节 -9,223,372,036,854,775,808 至 9,223,372,036,854,775,807

NUMERIC 类型

NUMERIC 数据类型属于精确数值,其精度为 38 位、标度为 9 位。精度是指数字所包含的位数。标度是指小数点后的位数。

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

名称 存储空间大小 说明 范围
NUMERIC 16 个字节 精度为 38 位、标度为 9 位的十进制值。 -99999999999999999999999999999.999999999 至 99999999999999999999999999999.999999999

浮点类型

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

名称 存储空间大小 说明
FLOAT64 8 个字节 双精度(近似)小数值。

浮点语义

使用浮点数时,需要考虑特殊的非数值: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 - 排序时,所有 值都会被视为相等。
  3. -inf
  4. 负数
  5. 0 或 -0 - 排序时,所有零值被视为相等。
  6. 正数
  7. +inf

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

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

布尔值类型

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

字符串类型

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

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

所有作用于 STRING 值的函数和运算符都会对 Unicode 字符(而非字节)进行运算。例如,应用于 STRING 输入的函数(如 SUBSTRLENGTH)计算的是 Unicode 字符数,而非字节数。比较运算是针对 Unicode 字符定义的。针对小于和 ORDER BY 的比较运算会逐个字符进行比较,而较低的 unicode 码位会被视为较低位的字符。

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

字节类型

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

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

日期类型

名称 说明 范围
DATE 表示逻辑日历日期。 0001-01-01 至 9999-12-31。

DATE 类型表示逻辑日历日期,与时区无关。DATA 值不代表特定的 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 代表一个时间点。每个 DATETIME 均包含以下内容:

  • month
  • 小时
  • 分钟
  • 秒钟
  • 亚秒

时间戳不同,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地理位置函数的结果或参数。

时间类型

名称 说明 范围
TIME 代表时间,与特定日期无关。 00:00:00 至 23:59:59.999999。

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 可精确到微秒。

标准格式

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

时区名称

时区名称来自 tz 数据库。如需不用太详尽的简明参考信息,请参阅维基百科上的 tz 数据库时区列表

格式
continent/[region/]city
示例
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 样式的时间戳进行计算,而这种样式的时间戳不能体现闰秒。闰秒只能通过测定真实世界时间的函数进行观察。在这些函数中,若存在闰秒,系统可能会跳过或重复时间戳的秒值。

数组类型

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

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

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

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

声明 ARRAY 类型

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

格式

ARRAY<T>

示例

类型声明 含义
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 不能直接包含其他 ARRAY,因此两个 ARRAY 之间会存在一个 STRUCT。

结构体类型

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

声明 STRUCT 类型

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

格式

STRUCT<T>

示例

类型声明 含义
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 的同名字段,则可直接比较个别字段。