构建一个触发器函数来使用postgres处理json数据

时间:2016-01-14 15:51:22

标签: json postgresql plpgsql

我在构建pl / pgsql函数来处理json数组时遇到了困难。

我从客户端收到的数据是一个用户问题答案列表,我将其存储在表格体验中名为“数据”的json类型字段中。

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();

我想构建一个触发器功能,将所有分数相加,并将结果保存在名为 accuracy_score 的字段中。这是我到目前为止所建立的:

logo.Save()

尝试运行时收到以下错误消息:

  

错误:查询“SELECT json_array_elements(New.data)”返回多行   语境:PL / pgSQL函数calculate_accuracy()在赋值时的第6行

我找不到如何解决这个问题。欢迎大家多多欢迎!

1 个答案:

答案 0 :(得分:2)

如果要更改插入行中的值,请使用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)