如何用PostgreSQL方言在Spanner中创建含SPANNER.COMMIT_TIMESTAMP列的表?
解决方案
1. 修正PostgreSQL方言下的建表语句
在Spanner的PostgreSQL方言中,提交时间戳列的语法和原生Spanner SQL不同,不能直接用SPANNER.COMMIT_TIMESTAMP作为列类型。正确的做法是将列类型定义为timestamptz(等价于timestamp with time zone),并通过DEFAULT spanner.commit_timestamp()设置自动填充的提交时间戳,同时保证非空约束。
修正后的建表语句:
CREATE TABLE dump_table ( id character varying NOT NULL, project_id character varying NOT NULL, user_id character varying NOT NULL, label character varying NOT NULL, value character varying NOT NULL, created_on timestamptz NOT NULL, updated_on timestamptz NOT NULL DEFAULT spanner.commit_timestamp(), deleted_on timestamptz, PRIMARY KEY(id, project_id) );
关键修正点:
- 将
updated_on的类型改为标准PG时间类型timestamptz,而非SPANNER.COMMIT_TIMESTAMP - 添加
DEFAULT spanner.commit_timestamp(),让Spanner自动在提交时填充该字段的时间戳 created_on保持timestamptz NOT NULL,由业务代码传入具体时间
2. 调整Golang代码适配
你的Go代码中有两个需要注意的细节:
- 表名不一致:建表语句用的是
dump_table,但代码中写的是pinectl_dump,需要统一 updated_on字段:因为已经设置了默认值,你可以选择不传该字段,或者继续传入spanner.CommitTimestamp(两种方式都生效)
调整后的代码示例:
// 方式1:利用默认值,不传入updated_on字段 mutation := spanner.InsertOrUpdate( "dump_table", // 修正表名 []string{"id", "project_id", "user_id", "label", "value", "created_on", "deleted_on"}, []interface{}{apiKey, projectID, userID, userLabel, apiKey, creationTimestamp, nil}, ) // 方式2:显式传入CommitTimestamp(和默认值效果一致) mutation := spanner.InsertOrUpdate( "dump_table", // 修正表名 []string{"id", "project_id", "user_id", "label", "value", "created_on", "updated_on", "deleted_on"}, []interface{}{apiKey, projectID, userID, userLabel, apiKey, creationTimestamp, spanner.CommitTimestamp, nil}, )
错误原因说明
你之前遇到的报错:
Expected "timezone"i:是因为SPANNER.COMMIT_TIMESTAMP with time zone的语法不符合PG方言规范,PG方言不支持将SPANNER.COMMIT_TIMESTAMP作为列类型- 移除
created_on后的类型错误:本质还是updated_on的类型定义不符合PG方言要求,PG方言只接受标准的PG数据类型,比如timestamptz,而不是SPANNER.COMMIT_TIMESTAMP
内容的提问来源于stack exchange,提问作者Aviral Srivastava
相关产品推荐
相关产品推荐

