有没有办法在添加新值时动态 update/increment 列值?

Is there a way to dynamically update/increment column values when a new value is added?

如果标题没有正确传达问题,我们深表歉意。

如果我有一个名为 Person 的 Postgres table 具有以下列和数据:

name | age | order |
John | 42  | 1     |
Sam  | 27  | 2     |
Phil | 19  | 3     |

顺序列是一个浮点数,用于确定客户端显示人员列表的顺序。

是否有最佳的性能方式来插入具有现有订单的 Person 但委托数据库自动增加订单列中的值?如果是,怎么做?

例如,如果我插入一个新人(Emma, 56, 2),我希望结果是

name | age | order |
John | 42  | 1     |
Sam  | 27  | 3     |
Phil | 19  | 4     |
Emma | 56  | 2     |

注意 Sam 和 Phil 现在增加了他们的订单。

可能的解决方案: 我可以利用 float 并获得先前订单值和当前订单的平均值。所以在上面的例子中,它将是 1(约翰)+ 2(插入的艾玛)/ 2。艾玛的新订单将是 1.5,如下所示:

name | age | order |
John | 42  | 1     |
Sam  | 27  | 2     |
Phil | 19  | 3     |
Emma | 56  | 1.5   |

但这需要多次数据库调用,因此出现了问题。

编辑:虽然我在最终实施中采用了 George Joseph 的回答,但实际回答问题的正确答案是 clamp 的。因此,我将他的回答标记为已接受。

以下是您如何处理您在示例中使用的可能解决方案

您将传递参数,param_name、param_age 和 param_order

 insert 
   into t 
with data
  as (select (max(order) +max(:param_order))/2 as possible_solution 
        from t
        where order<:param_order 
      )
select :param_name,:param_age,d.possible_solution 
  from data d

如果您想更新现有的条目,方法如下:

首先检查新值是否与现有值冲突。如果是这样,将现有值增加 1(这仍然适用于整数)。

我使用sort_order而不是order,因为后者在SQL中保留。

CREATE FUNCTION person_check_sort_order() RETURNS TRIGGER AS 
$def$
BEGIN
PERFORM * FROM person WHERE sort_order = new.sort_order;
IF FOUND THEN
UPDATE person SET sort_order = sort_order + 1 WHERE sort_order >= new.sort_order;
END IF;
RETURN new;
END;
$def$
LANGUAGE plpgsql;

CREATE TRIGGER person_insert_trg BEFORE INSERT ON person
FOR EACH ROW EXECUTE PROCEDURE person_check_sort_order();

或者你可以递归地做。这也适用于更新,并在订单号出现缺口时停止(假设为整数值):

CREATE OR REPLACE FUNCTION person_check_sort_order() RETURNS TRIGGER AS 
$def$
BEGIN
PERFORM * FROM person WHERE sort_order = new.sort_order;
IF FOUND THEN
UPDATE person SET sort_order = sort_order + 1 WHERE sort_order = new.sort_order;
END IF;
RETURN new;
END;
$def$
LANGUAGE plpgsql;
--DROP TRIGGER person_insert_trg ON person;
CREATE TRIGGER person_insert_trg BEFORE INSERT OR UPDATE OF sort_order ON person
FOR EACH ROW EXECUTE PROCEDURE person_check_sort_order();

我认为 PostgreSQL 中的序列可以解决这个问题

CREATE SEQUENCE serial START 101;

您可以在此处找到更多详细信息

https://www.postgresql.org/docs/9.5/sql-createsequence.html