在PostgreSQL中导入数据后,重复键值违反了唯一约束

Pet*_*ett 12 postgresql ruby-on-rails-3

我最近将我的rails应用程序迁移到PostgreSQL,以便利用全文搜索.

由于迁移与迁移到新的webhost同时发生,迁移步骤如下:

  1. 使用适当的database.yml文件部署应用程序和db:create/db:schema:在新服务器上加载
  2. mysqldump数据仅来自现有的MySQL生产数据库
  3. 将数据导入PostgreSQL数据库

应用程序正在成功运行,但在尝试向数据库添加新内容时出现问题.例如,当我运行rake任务来更新我的twitter feed时:

PG::Error: ERROR:  duplicate key value violates unique constraint "twitter_feeds_pkey" DETAIL:  Key (id)=(3) already exists.
Run Code Online (Sandbox Code Playgroud)

这也适用于所有其他模型,创建新文章,用户等.在开发中我可以看到发布插入语句n + 1次将成功保存记录而不会出错.

我的问题是:如何告诉PostgreSQL开始按现有数据顺序添加索引?

我已经阅读了这个REINDEX页面,但我认为这不是我正在寻找的操作.

a l*_*ame 27

在Rails中,您可以使用该命令

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

使User表的主键索引再次同步.


wil*_*ser 18

如果架构包含序列或序列列,则应将这些列重置为相应列中出现的最大值.(通常你不应该从文件中导入序列号,但是给它们自动增量的自由.)

对于所有导入的表,您应该识别序列字段并在其上运行以下代码.(将您的模式名称替换为"sch",将您的表名替换为"mytable",将您的名称列替换为"id")

WITH mx AS ( SELECT MAX(id) AS id FROM sch.mytable)
SELECT setval('sch.mytable_id_seq', mx.id) AS curseq
FROM mx
        ;
Run Code Online (Sandbox Code Playgroud)


a_h*_*ame 5

您可以自动化 wildplasser 的解决方案,以便所有序列与其关联列的当前最大值同步:

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$
Run Code Online (Sandbox Code Playgroud)

请注意,这只会工作,如果列已被定义为serialbigserial或已作出了一系列的“所有者”。