Google Cloud Spanner INSERT语句如何正确插入CURRENT_TIMESTAMP()时间戳
问题背景
根据Spanner官方文档说明,更新查询(update query)可以使用PENDING_COMMIT_TIMESTAMP(),示例代码如下:
const [rowCount] = await transaction.runUpdate({ sql: `UPDATE Albums SET LastUpdateTime = PENDING_COMMIT_TIMESTAMP() WHERE SingerId = 1`, });
希望在插入查询(insert query)中使用CURRENT_TIMESTAMP()插入当前时间戳,但在事务中执行时抛出如下错误:
INVALID_ARGUMENT: Could not cast literal "COMMIT_TIMESTAMP()" to type TIMESTAMP
可行解决方案
- 方案1:插入语句直接调用
PENDING_COMMIT_TIMESTAMP()
Spanner插入DML和更新DML对提交时间戳的支持规则一致,直接在SQL中把该函数作为值写入即可,不需要手动传入时间戳,函数会自动取事务最终提交的时间写入对应列。注意不要把函数名当成字符串字面量传入参数,必须直接写在SQL语句中,否则会触发类型转换错误,示例代码如下:const [rowCount] = await transaction.runUpdate({ sql: `INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, LastUpdateTime) VALUES (1, 1, '测试专辑', PENDING_COMMIT_TIMESTAMP())` }); - 方案2:代码侧生成时间戳通过参数化查询传入
如果你需要的是SQL执行时刻的时间而非事务提交时间,可以在业务代码中生成符合TIMESTAMP格式的时间值,通过参数化查询传入,不需要在SQL中调用时间函数:const currentTime = new Date().toISOString(); const [rowCount] = await transaction.runUpdate({ sql: `INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, LastUpdateTime) VALUES (@singerId, @albumId, @title, @currentTime)`, params: { singerId: 1, albumId: 1, title: '测试专辑', currentTime: currentTime } }); - 方案3:表结构设置时间列默认值
如果插入时默认都需要填充当前时间,可以在建表时给时间列设置默认值为CURRENT_TIMESTAMP(),同时开启allow_commit_timestamp选项,后续插入语句不需要显式指定该列,Spanner会自动填充时间:
建表SQL示例:
插入时直接省略该列即可:CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(100), LastUpdateTime TIMESTAMP NOT NULL OPTIONS ( allow_commit_timestamp = true, default_value = (CURRENT_TIMESTAMP()) ) ) PRIMARY KEY(SingerId, AlbumId);const [rowCount] = await transaction.runUpdate({ sql: `INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (1, 1, '测试专辑')` });
内容的提问来源于stack exchange,提问作者MAnI
相关产品推荐
相关产品推荐

