在对象内追加/推送或更新 Jsonb 数组
Append / Push or Update Jsonb array inside object
所以我在 postgresql(版本 12)
中得到了以下架构
-- items table
CREATE TABLE items
(
id CHAR(27) PRIMARY KEY NOT NULL DEFAULT new_ksuid(),
name TEXT NOT NULL,
item_code VARCHAR(120) NOT NULL UNIQUE,
qty_loc JSONB NOT NULL DEFAULT '{
"whQty": []
}',
categories TEXT[],
upper INTEGER NOT NULL DEFAULT 999,
under INTEGER NOT NULL DEFAULT 0,
price_max DECIMAL(20, 2),
price_min DECIMAL(20, 2),
price_avg DECIMAL(20, 2),
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
existed BOOLEAN NOT NULL DEFAULT false
);
CREATE INDEX idx_name_items ON items USING gin (name gin_trgm_ops);
CREATE INDEX idx_item_code_items ON items USING gin (item_code gin_trgm_ops);
和以下函数
CREATE
OR REPLACE FUNCTION upd_item_amount(wh_id CHAR(27),
item_id CHAR(27),
qty NUMERIC) RETURNS VOID
LANGUAGE plpgsql AS
'
DECLARE
entry items%ROWTYPE;
BEGIN
SELECT EXISTS(
(SELECT id
INTO entry
FROM items, jsonb_array_elements(items.qty_loc -> ''whQty'')
WHERE value ? ''whId''
AND value ->> ''whId'' = wh_id
AND items.id = item_id)
);
IF FOUND THEN
WITH whq_idx AS (
WITH whq AS (
WITH QTY_LOC_AGG AS (
SELECT jsonb_agg(value) AS loc
FROM items,
jsonb_array_elements(qty_loc -> ''whQty'')
)
SELECT items.id, loc
FROM items,
QTY_LOC_AGG
)
SELECT (''{'' || index - 1 || '',qty}'')::text[] as path
FROM whq,
jsonb_array_elements(whq.loc) WITH ORDINALITY arr(wh_quantity, index)
WHERE (wh_quantity ->> ''whId'') = wh_id
AND whq.id = item_id
)
UPDATE items
SET qty_loc = jsonb_build_object(''whQty'',
jsonb_set(qty_loc -> ''whQty'', whq_idx.path, qty, false)
)
FROM whq_idx
WHERE items.id = item_id;
ELSE
UPDATE items
SET qty_loc = jsonb_build_object(''whQty'',
jsonb_set(qty_loc -> ''whQty'',
qty_loc -> ''whQty'' || ''{"whId": wh_id, "qty": qty}''
)
)
WHERE items.id = item_id;
END IF;
END';
在交互式 psql 中,我可以使用以下 sql 语句从第一个 IF 语句中执行更新项目:
WITH whq_idx AS (
WITH whq AS (
WITH QTY_LOC_AGG AS (
SELECT jsonb_agg(value) AS loc
FROM items,
jsonb_array_elements(qty_loc -> ''whQty'')
)
SELECT items.id, loc
FROM items,
QTY_LOC_AGG
)
SELECT (''{'' || index - 1 || '',qty}'')::text[] as path
FROM whq,
jsonb_array_elements(whq.loc) WITH ORDINALITY arr(wh_quantity, index)
WHERE (wh_quantity ->> ''whId'') = wh_id
AND whq.id = item_id
)
UPDATE items
-- The error points to the following statement
SET qty_loc = jsonb_build_object(''whQty'',
jsonb_set(qty_loc -> ''whQty'', whq_idx.path, qty, false)
)
-- ^^^
FROM whq_idx
WHERE items.id = item_id;
但是当我通过 "SELECT upd_item_amount('warehouseID', 'itemID', amount_of_item)" 调用它(函数)时出现以下错误:
ERROR: function jsonb_set(jsonb, text[], numeric, boolean) does not exist
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
错误指向我代码中的粗体部分。
有人能给我指出正确的方向吗?感谢任何帮助。非常感谢。
ERROR: function jsonb_set(jsonb, text[], numeric, boolean) does not
exist
HINT: No function matches the given name and argument types. You might
need to add explicit type casts
你传递jsonb_set "qty"作为第三个参数,它是数字类型。但是 jsonb_set 将 JSONB 作为其第三个参数。 PostgreSQL 拒绝将数字隐式转换为 jsonb。您可以将其指定为 "qty"::text::jsonb
以强制进行转换。
所以我在 postgresql(版本 12)
中得到了以下架构-- items table
CREATE TABLE items
(
id CHAR(27) PRIMARY KEY NOT NULL DEFAULT new_ksuid(),
name TEXT NOT NULL,
item_code VARCHAR(120) NOT NULL UNIQUE,
qty_loc JSONB NOT NULL DEFAULT '{
"whQty": []
}',
categories TEXT[],
upper INTEGER NOT NULL DEFAULT 999,
under INTEGER NOT NULL DEFAULT 0,
price_max DECIMAL(20, 2),
price_min DECIMAL(20, 2),
price_avg DECIMAL(20, 2),
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
existed BOOLEAN NOT NULL DEFAULT false
);
CREATE INDEX idx_name_items ON items USING gin (name gin_trgm_ops);
CREATE INDEX idx_item_code_items ON items USING gin (item_code gin_trgm_ops);
和以下函数
CREATE
OR REPLACE FUNCTION upd_item_amount(wh_id CHAR(27),
item_id CHAR(27),
qty NUMERIC) RETURNS VOID
LANGUAGE plpgsql AS
'
DECLARE
entry items%ROWTYPE;
BEGIN
SELECT EXISTS(
(SELECT id
INTO entry
FROM items, jsonb_array_elements(items.qty_loc -> ''whQty'')
WHERE value ? ''whId''
AND value ->> ''whId'' = wh_id
AND items.id = item_id)
);
IF FOUND THEN
WITH whq_idx AS (
WITH whq AS (
WITH QTY_LOC_AGG AS (
SELECT jsonb_agg(value) AS loc
FROM items,
jsonb_array_elements(qty_loc -> ''whQty'')
)
SELECT items.id, loc
FROM items,
QTY_LOC_AGG
)
SELECT (''{'' || index - 1 || '',qty}'')::text[] as path
FROM whq,
jsonb_array_elements(whq.loc) WITH ORDINALITY arr(wh_quantity, index)
WHERE (wh_quantity ->> ''whId'') = wh_id
AND whq.id = item_id
)
UPDATE items
SET qty_loc = jsonb_build_object(''whQty'',
jsonb_set(qty_loc -> ''whQty'', whq_idx.path, qty, false)
)
FROM whq_idx
WHERE items.id = item_id;
ELSE
UPDATE items
SET qty_loc = jsonb_build_object(''whQty'',
jsonb_set(qty_loc -> ''whQty'',
qty_loc -> ''whQty'' || ''{"whId": wh_id, "qty": qty}''
)
)
WHERE items.id = item_id;
END IF;
END';
在交互式 psql 中,我可以使用以下 sql 语句从第一个 IF 语句中执行更新项目:
WITH whq_idx AS (
WITH whq AS (
WITH QTY_LOC_AGG AS (
SELECT jsonb_agg(value) AS loc
FROM items,
jsonb_array_elements(qty_loc -> ''whQty'')
)
SELECT items.id, loc
FROM items,
QTY_LOC_AGG
)
SELECT (''{'' || index - 1 || '',qty}'')::text[] as path
FROM whq,
jsonb_array_elements(whq.loc) WITH ORDINALITY arr(wh_quantity, index)
WHERE (wh_quantity ->> ''whId'') = wh_id
AND whq.id = item_id
)
UPDATE items
-- The error points to the following statement
SET qty_loc = jsonb_build_object(''whQty'',
jsonb_set(qty_loc -> ''whQty'', whq_idx.path, qty, false)
)
-- ^^^
FROM whq_idx
WHERE items.id = item_id;
但是当我通过 "SELECT upd_item_amount('warehouseID', 'itemID', amount_of_item)" 调用它(函数)时出现以下错误:
ERROR: function jsonb_set(jsonb, text[], numeric, boolean) does not exist
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
错误指向我代码中的粗体部分。
有人能给我指出正确的方向吗?感谢任何帮助。非常感谢。
ERROR: function jsonb_set(jsonb, text[], numeric, boolean) does not exist
HINT: No function matches the given name and argument types. You might need to add explicit type casts
你传递jsonb_set "qty"作为第三个参数,它是数字类型。但是 jsonb_set 将 JSONB 作为其第三个参数。 PostgreSQL 拒绝将数字隐式转换为 jsonb。您可以将其指定为 "qty"::text::jsonb
以强制进行转换。