Select 用于更新查询 returns 违反基数
Select for update query returns cardinality violation
我们在 Google 托管云数据库中 运行 Postgres 9.6.10 中的此查询:
WITH update AS
(UPDATE cart SET loyalty = loyalty || jsonb_insert('{}', '{coupon}', loyalty#>'{scan_coupon}' || ) WHERE id =
(SELECT id FROM cart WHERE id = AND status = and item_version = FOR UPDATE) returning *)
SELECT * FROM updated
cart
是一个 table,它以 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"
我已经确认 </code> 实际上是一个整数并指向现有的行,并且由于 <code>id
是主键,所以我不明白这怎么可能 return不止一排。
SELECT FOR UPDATE
是有问题的查询吗?如果 id
是主键,那么该查询 return 怎么可能超过一行。
看起来你可以简化为:
UPDATE cart
SET loyalty = loyalty || jsonb_build_object('coupon', loyalty->'scan_coupon') ||
WHERE id =
AND status =
AND item_version =
RETURNING *;
UPDATE
以与嵌套 SELECT ... FOR UPDATE
相同的方式锁定行。
而 jsonb_build_object()
更简单,与您的 jsonb_insert()
相同。或者更简单,但是:
SET loyalty = jsonb_insert(loyalty, '{coupon}', loyalty->'scan_coupon') ||
我和您一样感到惊讶,子查询(您不需要)会以某种方式 return 多于一行。似乎不可能。您确定这是错误消息的来源吗?
我们在 Google 托管云数据库中 运行 Postgres 9.6.10 中的此查询:
WITH update AS
(UPDATE cart SET loyalty = loyalty || jsonb_insert('{}', '{coupon}', loyalty#>'{scan_coupon}' || ) WHERE id =
(SELECT id FROM cart WHERE id = AND status = and item_version = FOR UPDATE) returning *)
SELECT * FROM updated
cart
是一个 table,它以 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"
我已经确认 </code> 实际上是一个整数并指向现有的行,并且由于 <code>id
是主键,所以我不明白这怎么可能 return不止一排。
SELECT FOR UPDATE
是有问题的查询吗?如果 id
是主键,那么该查询 return 怎么可能超过一行。
看起来你可以简化为:
UPDATE cart
SET loyalty = loyalty || jsonb_build_object('coupon', loyalty->'scan_coupon') ||
WHERE id =
AND status =
AND item_version =
RETURNING *;
UPDATE
以与嵌套 SELECT ... FOR UPDATE
相同的方式锁定行。
而 jsonb_build_object()
更简单,与您的 jsonb_insert()
相同。或者更简单,但是:
SET loyalty = jsonb_insert(loyalty, '{coupon}', loyalty->'scan_coupon') ||
我和您一样感到惊讶,子查询(您不需要)会以某种方式 return 多于一行。似乎不可能。您确定这是错误消息的来源吗?