After importing data in PostgreSQL, duplicate key value violates unique constraint

后端 未结 4 948
忘了有多久
忘了有多久 2021-02-02 17:51

I recently migrated my rails app to PostgreSQL in order to take advantage of fulltext search.

Since the migration coincided with moving to a new webhost, the steps for m

相关标签:
4条回答
  • 2021-02-02 18:00

    You can automate wildplasser's solution so that all sequences are synchronized with the current maximum value of their associated column:

    do
    $block$
    declare 
      r        record;
      stmt     text;
      max_id   integer;
    begin
      for r in (
                  select *
                  from (
                    select table_schema, 
                           table_name, 
                           column_name, 
                           pg_get_serial_sequence(table_schema||'.'||table_name, column_name) as col_sequence
                    from information_schema.columns
                    where table_schema not in ('pg_catalog', 'information_schema')
                  ) t
                  where col_sequence is not null
            ) 
      loop
        stmt := 'select coalesce(max('||r.column_name||'), 0) + 1 from '||r.table_schema||'.'||r.table_name;
        execute stmt into max_id;
        raise notice 'Next ID for %.%.% is %', r.table_schema, r.table_name, r.column_name, max_id;
        perform setval(r.col_sequence, max_id); 
      end loop;
    end;
    $block$
    

    Note that this will only work if the columns have been defined as serial, bigserial or have been made the "owner" of a sequence.

    0 讨论(0)
  • 2021-02-02 18:04

    In Rails you can use the command

    ActiveRecord::Base.connection.reset_pk_sequence!('users')

    to bring the primary key index for the User table in sync again.

    0 讨论(0)
  • 2021-02-02 18:16

    If the schema contains serial or sequence columns, you should reset these to the max value that occurs in the corresponding column. (normally you should not import the serials from a file, but give them the freedom to autoincrement.)

    For all imported tables you should identify the sequence fields and run the following code on them. (substitute your schema name for "sch", your table name for "mytable" and your id column name for "id")

    WITH mx AS ( SELECT MAX(id) AS id FROM sch.mytable)
    SELECT setval('sch.mytable_id_seq', mx.id) AS curseq
    FROM mx
            ;
    
    0 讨论(0)
  • 2021-02-02 18:16

    Another way is remove the primary key (id) from the columns (or don't dump the id). So your data would look like

    INSERT INTO book (name, price) VALUES ('Alchemist' , 10);
    

    instead of

    INSERT INTO book (id, name, price) VALUES (1 , 'Alchemist' , 10);
    

    This way, you won't have to reset the primary key after loading initial data

    0 讨论(0)
提交回复
热议问题