我们在 Google 管理的云数据库中的 Postgres 9.6.10 中运行此查询:
WITH update AS
(UPDATE cart SET loyalty = loyalty || jsonb_insert('{}', '{coupon}', loyalty#>'{scan_coupon}' || $1) WHERE id =
(SELECT id FROM cart WHERE id = $2 AND status = $3 and item_version = $4 FOR UPDATE) returning *)
SELECT * FROM updated
cart
是一个以 id
作为主键的表。 loyalty
是一个 jsonb 列,item_version
是一个在某些操作上递增的函数,但在更新 item_version
之前预计会发生几次更新。 status
是一个枚举类型。
在高并发更新下我们很少会遇到以下错误:
Cardinality_violation, file: "nodeSubplan.c", line: "1127", message: "more than one row returned by a subquery used as an expression", pg_code: "21000", routine: "ExecSetParamPlan", severity: "ERROR", unknown: "ERROR"
我已经确认 $2
实际上是一个整数并指向现有行,并且由于 id
是主键,我不知道它如何返回超过一排。
有问题的查询是SELECT FOR UPDATE
吗?如果 id
是主键,该查询如何返回多行。
最佳答案
看起来你可以简化为:
UPDATE cart
SET loyalty = loyalty || jsonb_build_object('coupon', loyalty->'scan_coupon') || $1
WHERE id = $2
AND status = $3
AND item_version = $4
RETURNING *;
UPDATE
锁定行的方式与嵌套 SELECT ... FOR UPDATE
的方式相同。
和jsonb_build_object()
更简单,与您的 jsonb_insert()
执行相同的操作。或者也许更简单:
SET loyalty = jsonb_insert(loyalty, '{coupon}', loyalty->'scan_coupon') || $1
我和你一样惊讶,子查询(你不需要)会以某种方式返回不止一行。看来不可能。您确定这是错误消息的来源吗?
关于postgresql - 选择更新查询返回基数违规,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56435529/