我有以下表格:
create table margins (
id serial primary key,
margins JSON,
created_at TIMESTAMP NOT NULL,
institution_uuid UUID NOT NULL,
created_by VARCHAR
);
和
create table margin_defaults (
id serial primary key,
model VARCHAR(255) NOT NULL,
margin FLOAT NOT NULL,
created_by VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
我将以下对象数组存储在列
margins
或表 margins
中
insert into margins (margins, created_at, institution_uuid, created_by) VALUES ('[{"model": "samsungS23","margin": "0.5","type": "CUSTOM"},{"model": "iphone",,"margin": "0.2","type": "CUSTOM"},{"model": "pixel","margin": "0.2","type": "CUSTOM"}]', '2023-12-12 15:38:40.642428', '51d8060e-5a31-4575-b56d-c5100e94d614', 'test-runner') RETURNING *;
在
margin_defaults
表中,我存储了不同类型边距的所有默认值。该表是追加/创建表,因此不会更新任何行。 margins
表也是如此。但是,当将新条目添加到 margin_defaults
表中时,我希望能够获取边距表中每个 institution_uuid
的最后一组条目,并使用相同的 更新
margins
列中的相应对象type
与新的 margin_defauts
条目相同,但仅当当前边距 type
设置为 DEFAULT
时。
到目前为止,我已经提出了以下触发器,但我收到了此错误:
ERROR: function jsonb_set(jsonb, text[], double precision) does not exist
LINE 3: jsonb_set(r.margins::jsonb, ('{' || tmp_position || ',m...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
QUERY: INSERT INTO margins (institution_uuid, margins, created_by) VALUES (
r.institution_uuid,
jsonb_set(r.margins::jsonb, ('{' || tmp_position || ',margin}')::text[], NEW.margin)::json,
NEW.created_by
)
CONTEXT: PL/pgSQL function update_margins_default_values_function() line 10 at SQL statement
我的触发点:
CREATE OR REPLACE FUNCTION update_margins_default_values_function()
RETURNS TRIGGER AS $$
DECLARE r RECORD;
DECLARE tmp_position int;
BEGIN
FOR r IN
SELECT DISTINCT ON (b.institution_uuid) * FROM (SELECT DISTINCT ON (institution_uuid) * FROM margins ORDER BY institution_uuid, created_at DESC) as b WHERE b.margins::jsonb@>'[{"type":"DEFAULT"}]' ORDER BY institution_uuid
LOOP
SELECT position FROM jsonb_array_elements(r.margins::jsonb) with ordinality arr(elem, position) INTO tmp_position WHERE elem->>'model'=NEW.model AND elem->>'type'='DEFAULT';
IF found THEN
INSERT INTO margins (institution_uuid, margins, created_by) VALUES (
r.institution_uuid,
jsonb_set(r.margins::jsonb, ('{' || tmp_position || ',margin}')::text[], NEW.margin)::json,
NEW.created_by
);
END IF;
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER update_margins_default_values_trigger
AFTER INSERT ON margin_defaults FOR EACH ROW EXECUTE PROCEDURE update_margins_default_values_function();
我正在尝试工作的小提琴 - sqlFiddle
试试这个..我修改了触发器函数,以正确更新
margins
表中JSON数组中的特定元素,使用带有动态构造路径的jsonb_set
函数并将新的边距值转换为jsonb
。
CREATE OR REPLACE FUNCTION update_margins_default_values_function()
RETURNS TRIGGER AS $$
DECLARE
r RECORD;
tmp_position int;
new_margin jsonb;
BEGIN
FOR r IN
SELECT DISTINCT ON (m.institution_uuid) m.* FROM margins m WHERE m.margins::jsonb @> '[{"type":"DEFAULT"}]' ORDER BY m.institution_uuid, m.created_at DESC
LOOP
SELECT position FROM jsonb_array_elements(r.margins::jsonb) WITH ORDINALITY arr(elem, position)
INTO tmp_position
WHERE elem->>'model' = NEW.model AND elem->>'type' = 'DEFAULT';
IF FOUND THEN
new_margin := to_jsonb(NEW.margin::text);
INSERT INTO margins (institution_uuid, margins, created_by) VALUES (
r.institution_uuid,
jsonb_set(r.margins::jsonb, ARRAY[tmp_position::text, 'margin'], new_margin),
NEW.created_by
);
END IF;
END LOOP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;