PostgreSQL sequence based on another column

后端 未结 8 1367
情话喂你
情话喂你 2020-11-30 01:33

Lets say I have a table as such:

Column   |     Type    |                        Notes
---------+------------ +----------------------------------------------         


        
相关标签:
8条回答
  • 2020-11-30 02:26

    Just a guess.

    INSERT INTO TABLE (ID, SEQ, DATA)
    VALUES
    (
     IDVALUE,
     (SELECT max(SEQ) +1 FROM TABLE WHERE ID = IDVALUU),
     DATAVALUE
    );
    
    0 讨论(0)
  • 2020-11-30 02:32

    No problem! We're going to make two tables, things and stuff. stuff will be the table you describe in your question, and things is the one it refers to:

    CREATE TABLE things (
        id serial primary key,
        name text
    );
    
    CREATE TABLE stuff (
        id integer references things,
        seq integer NOT NULL,
        notes text,
        primary key (id, seq)
    );
    

    Then we'll set things up with a trigger that will create a new sequence every time a row is created:

    CREATE FUNCTION make_thing_seq() RETURNS trigger
        LANGUAGE plpgsql
        AS $$
    begin
      execute format('create sequence thing_seq_%s', NEW.id);
      return NEW;
    end
    $$;
    
    CREATE TRIGGER make_thing_seq AFTER INSERT ON things FOR EACH ROW EXECUTE PROCEDURE make_thing_seq();
    

    Now we'll end up with thing_seq_1, thing_seq_2, etc, etc...

    Now another trigger on stuff so that it uses the right sequence each time:

    CREATE FUNCTION fill_in_stuff_seq() RETURNS trigger
        LANGUAGE plpgsql
        AS $$
    begin
      NEW.seq := nextval('thing_seq_' || NEW.id);
      RETURN NEW;
    end
    $$;
    
    CREATE TRIGGER fill_in_stuff_seq BEFORE INSERT ON stuff FOR EACH ROW EXECUTE PROCEDURE fill_in_stuff_seq();
    

    That'll ensure that when rows go into stuff, the id column is used to find the right sequence to call nextval on.

    Here's a demonstration:

    test=# insert into things (name) values ('Joe');
    INSERT 0 1
    test=# insert into things (name) values ('Bob');
    INSERT 0 1
    test=# select * from things;
     id | name
    ----+------
      1 | Joe
      2 | Bob
    (2 rows)
    
    test=# \d
                  List of relations
     Schema |     Name      |   Type   |  Owner
    --------+---------------+----------+----------
     public | stuff         | table    | jkominek
     public | thing_seq_1   | sequence | jkominek
     public | thing_seq_2   | sequence | jkominek
     public | things        | table    | jkominek
     public | things_id_seq | sequence | jkominek
    (5 rows)
    
    test=# insert into stuff (id, notes) values (1, 'Keychain');
    INSERT 0 1
    test=# insert into stuff (id, notes) values (1, 'Pet goat');
    INSERT 0 1
    test=# insert into stuff (id, notes) values (2, 'Family photo');
    INSERT 0 1
    test=# insert into stuff (id, notes) values (1, 'Redundant lawnmower');
    INSERT 0 1
    test=# select * from stuff;
     id | seq |        notes
    ----+-----+---------------------
      1 |   1 | Keychain
      1 |   2 | Pet goat
      2 |   1 | Family photo
      1 |   3 | Redundant lawnmower
    (4 rows)
    
    test=#
    
    0 讨论(0)
提交回复
热议问题