有没有办法在添加新值时动态 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;
您可以在此处找到更多详细信息
如果标题没有正确传达问题,我们深表歉意。
如果我有一个名为 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;
您可以在此处找到更多详细信息