【发布时间】:2022-08-19 02:44:40
【问题描述】:
如果我的表上有一个 SERIAL 列并插入一个值,该列会自动填充,但如果我之后调用 SELECT lastval() 来获取该值,即使它是同一个会话,我也会收到错误“lastval is not尚未在此会话中定义\"。这在 Postgres 中有效,但在 CockroachDB 中是一个错误。为什么会这样,我该如何解决?
如果我的表上有一个 SERIAL 列并插入一个值,该列会自动填充,但如果我之后调用 SELECT lastval() 来获取该值,即使它是同一个会话,我也会收到错误“lastval is not尚未在此会话中定义\"。这在 Postgres 中有效,但在 CockroachDB 中是一个错误。为什么会这样,我该如何解决?
lastval() 本身在 CockroachDB 和 Postgres 中的工作方式相同——它返回由 nextval() 在同一个 SQL 会话中生成的最新值,如果从未调用过则返回该错误。不同之处在于 CockroachDB 对 SERIAL 关键字的默认实现。 Postgres 通过创建一个序列并在您插入表时隐式调用 nextval 来实现这一点。 CockroachDB 改为调用 unique_rowid(),它的性能更高,但不会填充 lastval。您可以通过在使用 SERIAL 列创建表之前将 serial_normalization 变量设置为 virtual_sequence 来获得兼容的行为,和/或修改现有的串行列以使用虚拟序列。
例如,
CREATE SEQUENCE dummy_seq VIRTUAL;
ALTER TABLE users ALTER COLUMN id SET DEFAULT nextval('dummy_seq');
或者,您可以通过在插入时使用 RETURNING clause 来完全避免额外的数据库访问。
【讨论】: