如何在PostgreSQL中以事务方式插入max(order_field)+ 1行

时间:2014-04-24 19:13:02

标签: sql postgresql

我需要在PostgreSQL表中插入一行,其中包含最大值+ 1的列,用于表的行子集上的同一列。该列用于对该子集中的行进行排序。

我正在尝试更新插入后触发器中的列值,但我在不同的行中获取此列的重复值。

最好的方法是避免在短时间内有大量插入的并发环境中子集中的排序列的重复值?

提前致谢

编辑: 子集由同一个表的另一列定义:此列对所有相关行具有相同的值。

2 个答案:

答案 0 :(得分:1)

如果该列仅用于排序,则使用序列:

create table t (
    column1 integer,
    ordering_column serial
);

http://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-NUMERIC-TABLE

答案 1 :(得分:0)

新的交易安全答案:

要以事务安全的方式使用它,您可以使用此触发器,该触发器为每个不同的" set_id"创建序列。值:

create or replace function calculate_index() returns trigger 
as $$
declare my_indexer_name text;
begin
   my_indexer_name = 'my_indexer_name_' || NEW.my_set_id;
   if NOT EXISTS (SELECT * FROM pg_class WHERE relname = my_indexer_name)
   then
       execute 'create sequence ' || my_indexer_name;
   end if;
   select nextval(my_indexer_name) into NEW.my_index;
   return new;
end
$$
language plpgsql;

CREATE TRIGGER my_indexer_trigger 
     BEFORE INSERT ON my_table FOR EACH ROW
     EXECUTE PROCEDURE calculate_index();

如果您事先知道set_id可能的值,那么您可以手动创建名为' my_indexer_name_1' my_indexer_name_2'等的序列,然后您可以从触发器中消除if-then以上功能。

这是我最初的而非交易安全的答案:

我会创建一个新的帮助表,让我们称之为set_indexes:

create table set_indexes( set_id integer, max_index integer );

每条记录都有该组的set_id和最大索引值。 e.g:

 set_id,    max_index
 1          53
 2          12
 3          43
在触发器代码中

select max_index + 1 from set_indexes where set_indexes.set_id = NEW.my_set_id
   into NEW.my_index;
// Chek if the set_id is new:
if NEW.my_index is null then
   insert into set_indexes( set_id, max_index) values (NEW.my_set_id, 1);
   NEW.my_index = 0;
else
   update set_indexes set max_index = NEW.my_index where set_indexes.set_id = NEW.my_set_id;
end if;