0

I have below data table where I wants to create a unique id for data_id which will be unique per group_id (group_id and data_id should be unique) and for each group data_id should start from 1. How to create a DB sequence to achieve this ? Or any other better approach to achieve this ?

group_id  data_id 
UUID-1     1  
UUID-1     2
UUID-1     3
UUID-1     4
UUID-2     1
UUID-2     2
6
  • You can get that in a SELECT query using row_number() Commented Aug 11, 2020 at 11:47
  • @SekharDutta . . . I'm a little confused. Your data_id already seems to meet your requirements. You also define what you want a both a "unique id" and "unique id per group". Something either is or is not unique, so that is confusing. Commented Aug 11, 2020 at 11:49
  • Sorry if I am not clear. data_id column values I gave just for example, I wants that column to be populated automatically when a insert happens to the data table. group_id is a not null column Commented Aug 11, 2020 at 11:56
  • Usually a single sequence is better if you need it just as a key for joining and/or uniqueness. A sequence does not guarantee that each number is used as a key, some numbers may be missing because of insert conflicts or other things. Also, this kind of keys will be problematic if you need to modify group_id. Is there a specific reason why you need your keys to be like this? Commented Aug 11, 2020 at 12:20
  • I have other unique columns in data table. For my requirement I will always have group_id in context and based on data_id I have to find exact row/record, for some reason I have to keep length of this data_id column as small as possible. Commented Aug 11, 2020 at 12:37

2 Answers 2

1

DB Sequence will not help in this case. You can use trigger with some caveats:

Try this:

Create trigger function like below:

create or replace function trig_fun() 
returns trigger AS
$$
begin

select coalesce(max(data_id),0)+1 into new.data_id from my_table where group_id=new.group_id;

return new;

end;
$$
language plpgsql 

and attach above function on before insert event

create trigger trig_on_insert 
before insert on 
my_table
for each row
execute procedure trig_fun()

Limitations:

  1. If you delete the row of any group having max value for that group, it will reassign same number on next insert of same group.
  2. If you update any ID which is greater than others in that group then next value will be incremented from it.
Sign up to request clarification or add additional context in comments.

Comments

0
create function tgf_mytable_bi()
    returns trigger
    language plpgsql
as $f$
declare
    seq_name text;
begin
    seq_name := 'seq_'||new.group_id;
    -- Check is sequence already exists
    if (select count(*) = 0 from pg_class where relkind = 'S' and relname = seq_name) then
        -- New group detected
        -- Create new sequence for it
        execute format('create sequence %I', seq_name);
        -- Sequence exists, get next value from it
    end if;
    -- Generate next value for group
    new.data_id := nextval(seq_name);
end $f$;

create trigger trg_mytable_bi
    before insert on mytable
    for each row
    execute procedure tgf_mytable_bi();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.