postgresql - 选择更新查询返回基数违规
问题描述
我们在 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
我和你一样惊讶,子查询(你不需要)会以某种方式返回不止一行。似乎不可能。您确定这是错误消息的来源吗?
推荐阅读
- c# - 如何彻底删除 PictureBox(+ 释放内存)
- python - Delete dictionary in embedded list of dictionaries based on index number?
- python - Python HTTPServer: How to convert the extracted post data to python dictionary
- docker - Dockerize vue project
- reactjs - How to properly ask child components to do something in React Hooks
- javascript - Backbone 遗留应用程序中的“这个”/范围问题,_.bind 没有解决
- html - 即使我做到了,CSS也没有将项目向右对齐
- vuetify.js - 如何在 vuetify v-calendar 中使用“event-more-text”道具
- javascript - 无法在数据表中显示图像 (Javascript)
- sql - 从具有特定条件的 SQL 中创建的视图中选择