构建触发器函数以使用 postgres 处理 json 数据
building a trigger function to process json data with postgres
我正在努力构建一个 pl/pgsql 函数来处理 json 数组。
我从客户端收到的数据是我存储在 table [=24] 中名为 'data' 的 json 类型字段中的用户问题答案列表=]经验.
[
{"completed":false},
{"completed":false},
{"completed":false},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":75,"startTime":"2016-01-09T16:40:06.153Z","clickNb":1,"endTime":"2016-01-09T16:40:07.844Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":76,"startTime":"2016-01-09T16:40:08.487Z","clickNb":1,"endTime":"2016-01-09T16:40:12.482Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":77,"startTime":"2016-01-09T16:40:13.042Z","clickNb":1,"endTime":"2016-01-09T16:40:17.689Z"}
]
我想构建一个触发器函数来将所有分数相加并将结果保存在名为 accuracy_score 的字段中。这是我到目前为止构建的:
CREATE OR REPLACE FUNCTION calculate_accuracy() RETURNS TRIGGER AS $$
DECLARE
dataarray json;
BEGIN
dataarray := json_array_elements(New.data);
UPDATE experiences SET accuracy_score = subquery.score
FROM (SELECT SUM(dataarray->>'score') from dataarray) AS subquery
WHERE challenge_id = New.challenge_id;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER calculate_accuracy
AFTER INSERT ON experiences
FOR EACH ROW EXECUTE PROCEDURE calculate_accuracy();
当我尝试 运行 时收到以下错误消息:
ERROR: query "SELECT json_array_elements(New.data)" returned more than one row
CONTEXT: PL/pgSQL function calculate_accuracy() line 6 at assignment
我不知道如何解决这个问题。欢迎提供帮助!
如果您要更改插入行中的值,请使用 BEFORE TRIGGER 并在触发器函数中更改记录 NEW:
CREATE OR REPLACE FUNCTION calculate_accuracy() RETURNS TRIGGER AS $$
BEGIN
NEW.accuracy_score = (
SELECT sum((e->>'score')::int)
FROM json_array_elements(NEW.data) e);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER calculate_accuracy
BEFORE INSERT ON experiences
FOR EACH ROW EXECUTE PROCEDURE calculate_accuracy();
测试:
insert into experiences (challange_id, data)
values
(1,
'[
{"completed":false},
{"completed":false},
{"completed":false},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":75,"startTime":"2016-01-09T16:40:06.153Z","clickNb":1,"endTime":"2016-01-09T16:40:07.844Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":76,"startTime":"2016-01-09T16:40:08.487Z","clickNb":1,"endTime":"2016-01-09T16:40:12.482Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":77,"startTime":"2016-01-09T16:40:13.042Z","clickNb":1,"endTime":"2016-01-09T16:40:17.689Z"}
]'::json)
returning challange_id, accuracy_score;
challange_id | accuracy_score
--------------+----------------
1 | 3
(1 row)
我正在努力构建一个 pl/pgsql 函数来处理 json 数组。
我从客户端收到的数据是我存储在 table [=24] 中名为 'data' 的 json 类型字段中的用户问题答案列表=]经验.
[
{"completed":false},
{"completed":false},
{"completed":false},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":75,"startTime":"2016-01-09T16:40:06.153Z","clickNb":1,"endTime":"2016-01-09T16:40:07.844Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":76,"startTime":"2016-01-09T16:40:08.487Z","clickNb":1,"endTime":"2016-01-09T16:40:12.482Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":77,"startTime":"2016-01-09T16:40:13.042Z","clickNb":1,"endTime":"2016-01-09T16:40:17.689Z"}
]
我想构建一个触发器函数来将所有分数相加并将结果保存在名为 accuracy_score 的字段中。这是我到目前为止构建的:
CREATE OR REPLACE FUNCTION calculate_accuracy() RETURNS TRIGGER AS $$
DECLARE
dataarray json;
BEGIN
dataarray := json_array_elements(New.data);
UPDATE experiences SET accuracy_score = subquery.score
FROM (SELECT SUM(dataarray->>'score') from dataarray) AS subquery
WHERE challenge_id = New.challenge_id;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER calculate_accuracy
AFTER INSERT ON experiences
FOR EACH ROW EXECUTE PROCEDURE calculate_accuracy();
当我尝试 运行 时收到以下错误消息:
ERROR: query "SELECT json_array_elements(New.data)" returned more than one row CONTEXT: PL/pgSQL function calculate_accuracy() line 6 at assignment
我不知道如何解决这个问题。欢迎提供帮助!
如果您要更改插入行中的值,请使用 BEFORE TRIGGER 并在触发器函数中更改记录 NEW:
CREATE OR REPLACE FUNCTION calculate_accuracy() RETURNS TRIGGER AS $$
BEGIN
NEW.accuracy_score = (
SELECT sum((e->>'score')::int)
FROM json_array_elements(NEW.data) e);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER calculate_accuracy
BEFORE INSERT ON experiences
FOR EACH ROW EXECUTE PROCEDURE calculate_accuracy();
测试:
insert into experiences (challange_id, data)
values
(1,
'[
{"completed":false},
{"completed":false},
{"completed":false},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":75,"startTime":"2016-01-09T16:40:06.153Z","clickNb":1,"endTime":"2016-01-09T16:40:07.844Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":76,"startTime":"2016-01-09T16:40:08.487Z","clickNb":1,"endTime":"2016-01-09T16:40:12.482Z"},
{"completed":true,"score":1,"answerList":["1"],"QuestionId":77,"startTime":"2016-01-09T16:40:13.042Z","clickNb":1,"endTime":"2016-01-09T16:40:17.689Z"}
]'::json)
returning challange_id, accuracy_score;
challange_id | accuracy_score
--------------+----------------
1 | 3
(1 row)