标准 SQL 数据类型

BigQuery 不但支持简单的数据类型(如整数),还支持更为复杂的类型(如 ARRAY 和 STRUCT)。此页概述了每种数据类型,包括允许使用的值。有关数据类型字面量和构造函数的信息,请参阅词法结构和语法

数据类型属性

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

属性 说明 应用对象
可以为 Null 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 - 排序时,所有 NaN 值被视为相等。
  3. -inf
  4. 负数
  5. 0 或 -0 - 排序时,所有零值被视为相等。
  6. 正数
  7. +inf

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

  • NULL
  • NaN - 分组时,所有 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]:最多 6 个小数位(即达到微秒精度)

Geography 类型

名称 说明
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]:最多 6 个小数位(即达到微秒精度)

时间戳类型

名称 说明 范围
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]:最多 6 个小数位(即达到微秒精度)
  • [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 相同的时间。

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

闰秒

假设每分钟精确到 60 秒,时间戳即为世界协调时间 (UTC) 1970-01-01 00:00:00 的偏移量。闰秒不能通过存储的时间戳表示。

如果您在秒字段中输入包含“:60”的值来表示闰秒,则在转换为时间戳值时该闰秒不会保留。相反,该值在下一分钟的时间戳秒字段中代表“:00”。

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

数组类型

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

ARRAY 是一个包含零个或多个非 ARRAY 值元素的有序列表。不允许使用 ARRAY 的 ARRAY。产生 ARRAY 的 ARRAY 的查询会返回错误。相反,必须使用 SELECT AS STRUCT 结构将 STRUCT 插入到 ARRAY 之间。

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

  • 如果查询结果具有包含 NULL 元素的 ARRAY,则尽管可以在查询内部使用这些 ARRAY,BigQuery 仍会引发错误。
  • 尽管在查询中 NULL ARRAY 和 空 ARRAY 是两个不同的值,但 BigQuery 在查询结果中会将 NULL 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 之间存在 STRUCT,因为 ARRAY 不能直接包含其他 ARRAY。

结构体类型

名称 说明
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 的 STRUCT 类型,其中 ARRAY 由 64 位整数元素组成。

构建一个 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 的同名字段,可以直接比较单个字段。

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面