Possible to condense primary key/serial?

前端 未结 4 1125
挽巷
挽巷 2021-01-21 19:56

I have a database where everything is linked with foreign keys, so the Postgres knows exactly how the database is layed out..

Well, Lets say I have Table1 and Table2.

相关标签:
4条回答
  • 2021-01-21 20:09

    You probably don't want to do this generally, as gapless sequences are problematic for performance.

    If you want to do it as a cleanup step later you can use the rank() window function to achieve the desired effect.

    CREATE TABLE table1 (id integer primary key);
    INSERT INTO table1 values (1),(2),(4),(5);
    
    CREATE TABLE table2 (
      id serial primary key,
      rid integer references table1(id) ON UPDATE CASCADE
    );
    
    insert into table2 (rid) values (1),(1),(4),(4),(4),(5);
    
    
    
    UPDATE table1 
      SET id = gapless_id
    FROM (
      SELECT *, row_number() OVER () FROM table1
    ) AS x(old_id, gapless_id)
    WHERE id = x.old_id;
    

    Result:

    regress=# select * from table1 ;
     id 
    ----
      1
      2
      3
      4
    (4 rows)
    

    If your FK's aren't ON UPDATE CASCADE you can ALTER TABLE to make them so. This will be quite slow though, especially if there are no indexes on the foreign keys. A faster approach is to do the change in two passes:

    • Begin a transaction
    • LOCK TABLE table1;
    • Add a new_id column to table1 and populate it with the new IDs using row_number() as shown above
    • Drop foreign key constraints referring to table1(id)
    • Update all foreign keys to refer to the values in new_id
    • drop id in table1
    • rename the new_id column of table1 to id
    • re-create foreign key constraints
    • commit
    0 讨论(0)
  • 2021-01-21 20:19

    Except for very rare scenarios, gaps in the PK sequence are just right, to intent to get rid of them is a bad idea.

    0 讨论(0)
  • 2021-01-21 20:25

    It's best if a primary key never changes: Renumbering them is a PITA.

    If you need an ID for humans, one that has no gaps, A. Elein Mustain shows how to create a gapless sequence.

    0 讨论(0)
  • 2021-01-21 20:35

    Look into on update cascade and on delete cascade.

    create table table_1 (
        id integer
            primary key,
        name char(30)
    );
    create table table_2 (
        id integer
            primary key,
        table_1_id integer
            references table_1
            on update cascade
            on delete cascade,
        detail char(30)
    );
    
    0 讨论(0)
提交回复
热议问题