使用 Cloud Spanner 的数据定义语言 (DDL) 来执行以下操作:
- 创建数据库。
- 创建、修改或删除数据库中的表。
- 添加、修改或删除表中的列。
- 创建或删除数据库中的索引。
DDL 语法
statement: { create_database | alter_database | create_table | create_index | alter_table | drop_table | drop_index } create_database: CREATE DATABASE database_id alter_database: ALTER DATABASE database_id action where action is: SET OPTIONS ( optimizer_version = { 1 ... 2 | null }, version_retention_period = { 'duration' | null } ) create_table: CREATE TABLE ( [ { column_name data_type [NOT NULL] [AS ( expression ) STORED] [ options_def ] | table_constraint } [, ... ] ] ) PRIMARY KEY ( [ column_name [ { ASC | DESC } ], ...] ) [, INTERLEAVE IN PARENT table_name [ ON DELETE { CASCADE | NO ACTION } ] ] where data_type is: { scalar_type | array_type } and options_def is: { OPTIONS ( allow_commit_timestamp = { true | null } ) } and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) | FOREIGN KEY ( column_name [, ... ] ) REFERENCES ref_table ( ref_column [, ... ] ) } create_index: CREATE [ UNIQUE ] [ NULL_FILTERED ] INDEX index_name ON table_name ( key_part [, ...] ) [ storing_clause ] [ , interleave_clause ] where index_name is: {a—z|A—Z}[{a—z|A—Z|0—9|_}+] and key_part is: column_name [ { ASC | DESC } ] and storing_clause is: STORING ( column_name [, ...] ) and interleave_clause is: INTERLEAVE IN table_name alter_table: ALTER TABLE table_name action [, ... ] where action is: ADD [ COLUMN ] column_name data_type [ NOT NULL ] [AS ( expression ) STORED] [ options_def ] DROP [ COLUMN ] column_name ADD table_constraint DROP CONSTRAINT constraint_name SET ON DELETE { CASCADE | NO ACTION } ALTER [ COLUMN ] column_name { { data_type } [ NOT NULL ] | SET [ options_def ] } and data_type is: { scalar_type | array_type } and options_def is: { OPTIONS ( allow_commit_timestamp = { true | null } ) } and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) | FOREIGN KEY ( column_name [, ... ] ) REFERENCES ref_table ( ref_column [, ... ] ) } drop_table: DROP TABLE table_name drop_index: DROP INDEX index_name scalar_type: { BOOL | INT64 | FLOAT64 | NUMERIC | STRING( length ) | BYTES( length ) | DATE | TIMESTAMP } length: { int64_value | MAX } array_type: ARRAY< scalar_type > int64_value: { decimal_value | hex_value } decimal_value: [-]0—9+ hex_value: [-]0x{0—9|a—f|A—F}+ database_id: {a—z}[{a—z|0—9|_|-}+]{a—z|0—9} table_name, column_name, index_name: {a—z|A—Z}[{a—z|A—Z|0—9|_}+]
批注:
- 方括号“[ ]”表示可选的子句。
- 圆括号“( )”表示文本括号。
- 竖线“|”表示逻辑“或”(OR) 。
- 大括号“{ }”括起一组可选项。
- 英文逗号后跟英文省略号表示前一项可能在英文逗号分隔列表中重复。
item [, ...]
表示一或多项,而[item, ...]
表示零或更多项。 - 英文逗号“,”表示文本逗号。
- 英文尖括号“<>”表示文本尖括号。
- 连接号“—”表示其两侧项之间的值范围。
- 加号“+”表示前一项可以重复。
预留关键字
Cloud Spanner 的 DDL 中预留了一些字(如类型名称)。如果您需要在架构中使用预留关键字作为标识符,请将其用英文反引号 (`
) 括起来。如需获取 Cloud Spanner 中预留关键字的完整列表,请参阅词汇结构和语法。
例如:
CREATE TABLE MyTable ( RowId INT64 NOT NULL, `Int64` INT64 ) PRIMARY KEY (RowId);
命名规则
以下规则适用于表、列、索引和外键限制条件名称。
长度不得少于 1 个字符。
最多可包含 128 个字符。
必须以大写或小写字母开头。
可以包含大写和小写字母、数字和下划线,但不能包含连字符。
无法创建两个同名的 Cloud Spanner 对象。这包括仅大小写不同的名称。例如,以下代码段中的第二个语句失败,因为表名称仅大小写不同。
CREATE TABLE MyTable (col1 INT64) PRIMARY KEY (col1); CREATE TABLE MYTABLE (col1 INT64) PRIMARY KEY (col1);
引用 DDL 语句中的其他架构对象(例如主键的列名或索引中的表名和列名)时,请务必使用每个实体名称的原始大小写。例如,假设使用以下语句创建
Singers
表。CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX), BirthDate DATE, ) PRIMARY KEY(SingerId);
以下命令失败并显示消息
Table not found: singers
,因为它对Singers
表使用不同的大小写。CREATE INDEX SingersByFirstLastName ON singers(FirstName, LastName)
Cloud Spanner 架构对象名称在 SQL 查询中不区分大小写。例如,假设使用以下语句创建
MyTable2
表。CREATE TABLE MyTable2 (col1 INT64) PRIMARY KEY (col1);
以下查询均会成功,因为架构对象名称对于查询不区分大小写。
SELECT col1 FROM MyTable2 LIMIT 1 SELECT COL1 FROM MYTABLE2 LIMIT 1 SELECT COL1 FROM mytable2 LIMIT 1 INSERT INTO MYTABLE2 (col1) VALUES(1)
DATABASE 语句
CREATE DATABASE
创建 Cloud Spanner 数据库时,您必须使用 CREATE DATABASE
语句,该语句用于定义数据库的 ID:
CREATE DATABASE database_id where database_id {a—z}[{a—z|0—9|_|-}+]{a—z|0—9}
参数
database_id
- 要创建的数据库的名称。请参阅命名规则。
ALTER DATABASE
更改表的定义。
语法
ALTER DATABASE database_id action where database_id is: {a—z}[{a—z|0—9|_|-}+]{a—z|0—9} and action is: SET OPTIONS ( optimizer_version = { 1 ... 2 | null }, version_retention_period = { 'duration' | null } )
说明
ALTER DATABASE
用于更改现有数据库的定义。
SET OPTIONS
- 使用此子句在架构层次结构的数据库级层设置一个选项。
参数
database_id
- 要更改其特性的数据库的名称。如果名称是保留字或包含连字符,请将其用反引号 (
`
) 括起来。如需详细了解数据库命名规则,请参阅本文档中的命名惯例。
options_def
optimizer_version = { 1 ... 2 | null }
选项允许您指定要使用的查询优化器版本。默认情况下,这是优化器的最新版本,但您可以指定任何可用的优化器版本。将此选项设置为null
等同于将其设置为最新版本,当前的最新版本为 2。如需了解详情,请参阅查询优化器。version_retention_period = { 'duration' | null }
是 Cloud Spanner 为该数据库保留所有数据和架构版本的时间段。时长范围必须在[1h, 7d]
范围内,并且可以以天、小时、分钟或秒为单位指定。例如,值1d
、24h
、1440m
和86400s
是等效的。将值设置为null
可将保留期限重置为默认值,即 1 小时。此选项可用于时间点恢复。如需了解详情,请参阅时间点恢复。
数据类型
标量
在 DDL 中使用标量类型的语法如下:
{ BOOL | INT64 | FLOAT64 | NUMERIC | STRING( length ) | BYTES( length ) | DATE | TIMESTAMP } length: { int64_value | MAX } int64_value: { decimal_value | hex_value } decimal_value: [-]0—9+ hex_value: [-]0x{0—9|a—f|A—F}+
int64_value
必须对应到 -9,223,372,036,854,775,808 (-263) 至 9,223,372,036,854,775,807 (263 − 1) 之间的整数。该值可以使用十进制或十六进制表示法指定。如果采用十六进制形式,则需要添加 0x
前缀,其中 x
采用小写形式。
STRING
STRING
是一个长度可变的 Unicode 字符串。其值必须为有效的 Unicode 字符串。长度是必需的属性,用于表示可以存储在该字段中的 Unicode 字符(非字节)的最大数量。
注意:
如果新值不是有效的 Unicode 字符串或超过指定长度,则写入该列的操作将被拒绝。
length
可以是 [1, 2621440] 范围内的整数。对于长度无法预测或无需限制的字段,可以将
length
方便地设为值MAX
以进行验证,此值等于 2621440。只有存储的字符串的实际长度会影响存储费用;指定
MAX
不会占用任何额外的存储容量。在服务器上接收数据时,Cloud Spanner 要求将 Unicode 字符串转换为 UTF-8 编码格式。
排序规则由 Unicode 字符数值决定(技术上由码位决定,其因组合字符而存在细微差别)。对于 ASCII 字符串,排序规则采用传统排序。
可以在创建表之后缩短列的长度,但这样做需要 Cloud Spanner 验证现有数据在长度限制以内。
BYTES
BYTES
是一个长度可变的二进制字符串。长度是必需的属性,用于表示可以存储在该字段中的最大字节数。
注意:
如果写入的新值超过指定的长度,则写入列的操作将被拒绝。
length
可以是 [1, 10485760] 范围内的整数,或方便地设为值MAX
以进行验证,此值等于 10485760。只有实际存储的字节会影响存储费用;指定
MAX
不会占用任何额外的存储容量。可以在创建表之后缩短列的长度,但这样做需要 Cloud Spanner 验证现有数据在长度限制以内。
DATE
- 与时区无关的日期。
- 日期的合法区间范围为 [0001-01-01, 9999-12-31]。如果写入日期列的值超出该区间,则写入的内容将被拒绝。
- 如需了解详情和标准格式,请参阅数据类型。
TIMESTAMP
- 精度为纳秒的时间戳。
- 与时区无关,范围为 [0001-01-01 00:00:00 至 10000-01-01 00:00:00)。
- 如需了解详情和标准格式,请参阅数据类型。
数组
在 DDL 中使用 ARRAY
类型的语法如下:
ARRAY< scalar_type >
Cloud Spanner 支持标量数组。数组的主要目的是以有效利用空间的方式存储一组值。数组的设计不是为了提供对单独元素的访问;要读取或写入单个元素,您必须读取或写入整个数组。
如果您的应用使用矢量或重复字段之类的数据结构,您可以将其状态保存在一个 Cloud Spanner 数组中。
以下示例展示了使用多个 ARRAY
类型的列的 Singers
的另一种定义:
CREATE TABLE Singers ( SingerId INT64, FeaturedSingerIds ARRAY<INT64>, SongNames ARRAY<STRING(MAX)>, ) PRIMARY KEY (SingerId) ...;
注意:
- 不支持具有子类型
ARRAY
(嵌套数组)的数组。 - 数组与标量值一样,总大小不能超过 10 MiB。
- 数组不能用作键列。
在
CREATE TABLE
语句中,您可以创建ARRAY
类型的列,并为其添加NOT NULL
注释。创建表后,您则不能为
ARRAY
类型的列添加NOT NULL
注释,也不能为ARRAY
类型的现有列添加NOT NULL
注释。
TABLE 语句
CREATE TABLE
定义新表。
语法
CREATE TABLE table_name ( [ { column_name data_type [ NOT NULL ] [AS ( expression ) STORED] [ options_def ] | table_constraint } [, ... ] ] ) PRIMARY KEY ( [column_name [ { ASC | DESC } ], ...] ) [, INTERLEAVE IN PARENT table_name [ ON DELETE { CASCADE | NO ACTION } ] ] where data_type is: { scalar_type | array_type } and options_def is: { OPTIONS ( allow_commit_timestamp = { true | null } ) } and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) | FOREIGN KEY ( column_name [, ... ] ) REFERENCES ref_table ( ref_column [, ... ] ) }
说明
CREATE TABLE
定义当前数据库中的新表。
参数
table_name
- 要创建的表的名称。如需了解命名准则,请参阅命名规则。
column_name
- 要创建的列的名称。如需了解命名准则,请参阅命名规则。
data_type
NOT NULL
此可选列注释指定了插入新行的所有变更都需要该列。
您不能将 NOT NULL 列添加到现有表。对于大部分列类型,您可以通过以下方法解决此限制:
对于
ARRAY
类型的列,只有在创建表时才能使用 NOT NULL 注释。之后,您不能向ARRAY
类型的列添加 NOT NULL 注释。对于所有其他列类型,您可以添加一个可以为 Null 的列,在所有行写入值以填充该列,然后对该列使用 NOT NULL 注释更新您的架构。
AS ( expression ) STORED
此子句创建了一个列作为“生成的列”,该列的值被定义为同一行中其他列的函数。
表达式可以是可分配给列数据类型的任何有效 SQL 表达式,但存在以下限制。
表达式只能引用同一表中的列。
表达式不能包含子查询。
表达式不能包含非确定性函数,例如
PENDING_COMMIT_TIMESTAMP()
、CURRENT_DATE()
、CURRENT_TIMESTAMP()
。您无法修改生成的列的表达式。
表达式后的
STORED
属性会将函数结果与表的其他列一起存储。对任何被引用的列的后续更新都将导致对表达式重新求值和存储。不允许有无
STORED
属性的生成的列。不允许直接写入生成的列。
生成的列不能用作主键或是主键的一部分。但是,它们可作为二级索引键。
生成的列或生成的列引用的任何列都不允许使用列选项
allow_commit_timestamp
。您无法更改已生成列的数据类型,也无法更改由生成的列引用的任何列。
您无法删除由生成的列引用的列。
如需了解如何使用生成的列,请参阅创建和管理生成的列。
PRIMARY KEY ( [
column_name
[ { ASC | DESC } ], ...]
每个表都必须有一个主键,并且该主键可以由该表的零列或多列组成。
为主键列名称添加
DESC
注释会将数据的实际布局从升序(默认)更改为降序。
如需了解详情,请参阅架构和数据模型。
[, INTERLEAVE IN PARENT
table_name
[ ON DELETE { CASCADE | NO ACTION } ] ]
此子句定义了一个子对父的表关系,这会使父行和子行产生物理交错。父行的主键列必须在名称和类型上与子行的主键列前缀相匹配。如果相应的父行不存在,则向子表添加行将失败。父行可以已经存在于数据库中,也可以在将子行插入到同一事务中之前插入。
可选的
ON DELETE
子句定义了在某项变更尝试删除父行时ChildTable
中行的行为。受支持的选项有:CASCADE
:子行被删除。NO ACTION
:子行不会被删除。如果删除父行会留下子行,这样会违反父子关系的参照完整性,因此写入操作将失败。
您可以省略
ON DELETE
子句,并使用ON DELETE NO ACTION
默认值。
如需了解详情,请参阅架构和数据模型。
CONSTRAINT
constraint_name
- 表限制条件的可选名称。如果未指定名称,Cloud Spanner 会为限制条件生成名称。可以从 Cloud Spanner 的信息架构中查询限制条件名称(包括生成的名称)。
CHECK (
expression
)
借助
CHECK
限制条件,您可以指定一个或多个列的值必须满足布尔值表达式。expression
可以是任何计算结果为BOOL
的有效 SQL 表达式。以下限制适用于检查限制条件
expression
术语。表达式只能引用同一表中的列。
表达式必须直接引用至少一个非生成的列,无论是直接引用,还是通过引用非生成的列的生成的列进行引用。
表达式无法引用已设置
allow_commit_timestamp
选项的列。表达式不能包含子查询。
表达式不能包含非确定性函数,例如
CURRENT_DATE()
和CURRENT_TIMESTAMP()
。
如需了解详情,请参阅创建和管理检查限制条件。
FOREIGN KEY (
column_name
[, ... ] ) REFERENCES
ref_table
(
ref_column
[, ... ] )
使用此子句定义外键限制条件。在关系的引用表上定义了一个外键,它引用了“被引用”表。这两个表的外键列称为“引用”列和“被引用”列,其行值是键。
外键限制条件要求此表的一个或多个列只能包含被引用表的被引用列中的值。
创建外键时,除非引用了整个主键,否则系统会在被引用表上自动创建一个唯一的限制条件。如果无法满足唯一限制条件,则整个架构更改都将失败。
引用列数和被引用列数必须相同。顺序也很重要。也就是说,第一个引用列引用第一个被引用列,第二个引用列引用第二个被引用列,以此类推。
引用列和被引用列必须具有匹配类型,并且必须支持等式运算符 ('=')。这些列还必须可编入索引。 不允许使用类型为
ARRAY
和NUMERIC
的列。无法使用
allow_commit_timestamp=true
选项在列上创建外键。
如需了解详情,请参阅外键。
OPTIONS ( allow_commit_timestamp = { true | null } )
allow_commit_timestamp
选项允许插入和更新操作请求 Cloud Spanner 将事务的提交时间戳写入列中。如需了解详情,请参阅提交时间戳。
ALTER TABLE
更改表的定义。
语法
ALTER TABLE table_name action [, ... ] where action is: ADD [ COLUMN ] column_name data_type [ NOT NULL] [AS ( expression ) STORED] [ options_def ] DROP [ COLUMN ] column_name ADD table_constraint DROP CONSTRAINT constraint_name SET ON DELETE { CASCADE | NO ACTION } ALTER [ COLUMN ] column_name { { data_type } [ NOT NULL ] | SET [ options_def ] } and data_type is: { scalar_type | array_type } and options_def is: { OPTIONS (allow_commit_timestamp = { true | null } ) } and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) | FOREIGN KEY ( column_name [, ... ] ) REFERENCES ref_table ( ref_column [, ... ] ) }
说明
ALTER TABLE
用于更改现有表的定义。
ADD COLUMN
- 使用与
CREATE TABLE
相同的语法向表添加新列。
DROP COLUMN
从表中丢弃列。
您无法删除由生成的列引用的列。
不允许删除由
CHECK
限制条件引用的列。
ADD
table_constraint
使用与
CREATE TABLE
相同的语法向表添加新的限制条件。对于外键,在添加外键之前验证现有数据。如果任何现有受限键没有对应的被引用键,或者被引用键不是唯一的,则表示违反了限制条件,并且
ALTER
语句会失败。对于
CHECK
限制条件,系统会根据限制条件立即验证新数据。此外,系统还会启动一个长时间运行的进程,以根据限制条件验证现有数据。如果任何现有数据不符合限制条件,则系统会回滚检查限制条件。以下限制适用于检查限制条件
expression
术语。表达式只能引用同一表中的列。
表达式必须直接引用至少一个非生成的列,无论是直接引用,还是通过引用非生成的列的生成的列进行引用。
表达式无法引用已设置
allow_commit_timestamp
选项的列。表达式不能包含子查询。
表达式不能包含非确定性函数,例如
CURRENT_DATE()
和CURRENT_TIMESTAMP()
。
DROP CONSTRAINT
constraint_name
- 删除对表的指定限制条件以及任何关联索引(如果适用)。
SET ON DELETE { CASCADE | NO ACTION }
此更改只能应用于父子表的子表、交错表和关系。如需了解详情,请参阅架构和数据模型。
ON DELETE CASCADE
子句表明,如果父表中的行被删除,也会自动删除该表中的子行。子行是以相同主键开头的所有行。如果子表没有此注释,或注释为ON DELETE NO ACTION
,则您必须先删除子行,然后才能删除父行。
ALTER COLUMN
- 用于更改表上现有列的定义。
参数
table_name
- 要更改的现有表的名称。
column_name
- 新列或现有列的名称。您无法更改表的键列。
data_type
新列的数据类型或现有列的新数据类型。
您无法更改已生成列的数据类型,也无法更改由生成的列引用的任何列。
不允许对
CHECK
限制条件中引用的任何列更改数据类型。options_def
(allow_commit_timestamp=true)
选项允许插入和更新操作请求 Cloud Spanner 将事务的提交时间戳写入列中。如需了解详情,请参阅提交时间戳。
table_constraint
- 表的新表限制条件。
constraint_name
- 新限制条件或现有限制条件的名称。
ref_table
- 外键限制条件中的“被引用”表。
ref_column
- 外键限制条件中的“被引用”列。
DROP TABLE
移除表。
语法
DROP TABLE table_name
说明
使用 DROP TABLE
语句从数据库中移除表。
DROP TABLE
不可恢复。如果表存在索引,或者存在与之交错的表或索引,则无法删除表。
DROP TABLE
语句会自动丢弃表的外键和外键支持性索引。
参数
table_name
- 要丢弃的表的名称。
INDEX 语句
创建索引
使用 CREATE INDEX
语句定义二级索引。
语法
CREATE [ UNIQUE ] [ NULL_FILTERED ] INDEX index_name ON table_name ( key_part [, ...] ) [ storing_clause ] [ , interleave_clause ] where index_name is: {a—z|A—Z}[{a—z|A—Z|0—9|_}+] and key_part is: column_name [ { ASC | DESC } ] and storing_clause is: STORING ( column_name [, ...] ) and interleave_clause is: INTERLEAVE IN table_name
说明
Cloud Spanner 会自动将每个表的主键列编入索引。
您可以使用 CREATE INDEX
为其他列创建二级索引。针对非主键列添加二级索引有助于更高效地查找此类列中的数据。如需了解详情,请参阅二级索引。
参数
UNIQUE
- 表示这个二级索引会对要编入索引的数据执行一个
UNIQUE
限制条件。UNIQUE
限制条件会使任何产生重复索引键的事务都遭到拒绝。如需了解详情,请参阅唯一索引。
NULL_FILTERED
- 表示这个二级索引不会将
NULL
值编入索引。如需了解详情,请参阅将 NULL 值编入索引。
index_name
- 要创建的索引的名称。如需了解命名准则,请参阅命名规则。
table_name
- 要编入索引的表的名称。
INTERLEAVE IN
定义了一个在其中交错索引的表。如果
T
是在其中交错索引的表,则:T
必须是要编入索引的表的父表T
的主键必须是索引的键前缀。
什么时候应该创建交错索引?如果要用于索引操作的索引键与表的键相匹配,且表中的行与相应的索引行具有数据局部性关系,则可能需要在该表中交错索引。
例如,如果您想在
Songs
的所有行中为Singers
的特定行编制索引,您的索引键应包含SingerId
和SongName
,并且如果您经常在从索引中获取某个歌手的歌曲时获取该歌手的信息,您的索引将很适合在Singers
中交错。创建二级索引中SongsBySingerSongName
的定义即为创建这种交错索引的一个示例。与交错表相同,交错索引中的条目也会与父表中对应的行一起存储。如需了解详情,请参阅数据库分片。
DESC
- 为对应的索引列定义降序扫描顺序。使用标记为
DESC
的索引列扫描表时,扫描的行将按照该索引列降序显示。如果未指定排序顺序,则默认为升序 (ASC
)。
STORING
- 提供了一种将表中的数据复制到该表上的一个或多个二级索引的机制。以额外的存储空间为代价,当使用二级索引查找数据时,该机制可以缩短读取延迟时间,因为它不需要在找到索引中的所需条目后从主表中检索数据。请参阅 STORING 子句查看示例。
DROP INDEX
移除二级索引。
语法
DROP INDEX index_name
说明
使用 DROP INDEX
语句删除二级索引。
参数
index_name
- 要丢弃的索引的名称。
以下规则适用于数据库 ID。
- 必须以小写字母开头。
- 可以包含小写字母、数字、下划线和连字符,但不能包含大写字母。
- 不能以下划线或连字符结尾。
- 如果是预留字词或包含连字符,则必须用英文反引号 (
`
) 括起来。 - 长度在 2-30 个字符之间。
- 创建后无法更改。