postgresql重复键违反了唯一约束

时间:2010-12-15 09:16:43

标签: postgresql

嗨我有一个问题,我知道这次发布很多次,但我找不到问题的答案。问题是我有一个表和一列“id”我希望它是正常的唯一数字。这种类型的列是串行的,每个插入后的下一个值是从一个序列中提交的,所以一切似乎都可以,但它仍然有时显示此错误。我不知道为什么?在文档中它是写的顺序是傻瓜教授,并始终有效。如果我向该列添加UNIQUE约束,那么它会是什么?我曾多次在Postres工作,但这个错误第一次出现在我面前。我做的一切正常,我之前从未遇到过这个问题。你能帮我找到可以在将来用于所有将要创建的表的答案吗?让我们说我们有这样简单的事情:

CREATE TABLE comments
(
  id serial NOT NULL,
  some_column text NOT NULL,
  CONSTRAINT id_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE interesting.comments OWNER TO postgres;

如果我添加:

ALTER TABLE comments ADD CONSTRAINT id_id_key UNIQUE(id)

是否应该采取或是否还有其他事情要做?

12 个答案:

答案 0 :(得分:47)

This article explains您的序列可能不同步,您必须手动将其重新同步。

如果网址发生变化,请摘自文章摘录:

  

如果在尝试将数据插入PostgreSQL时收到此消息   数据库:

ERROR:  duplicate key violates unique constraint
     

这可能意味着您所在的表中的主键序列   与某种程度上的合作,可能因某种程度上变得不同步   导入过程(或类似的东西)。把它叫做'#34; bug   设计",但似乎你必须手动重置主要   从转储文件恢复后的密钥索引。无论如何,看看是否   您的值不同步,请运行以下两个命令:

SELECT MAX(the_primary_key) FROM the_table;   
SELECT nextval('the_primary_key_sequence');
     

如果第一个值高于第二个值,则序列为   不同步。备份PG数据库(以防万一),然后运行thisL

SELECT setval('the_primary_key_sequence', (SELECT MAX(the_primary_key) FROM the_table)+1);
     

这会将序列设置为下一个可用值更高的值   比序列中任何现有的主键。

答案 1 :(得分:4)

对于以后的搜索,请使用“不要冲突”。

答案 2 :(得分:3)

主键已经保护您不会插入重复值,就像您遇到错误时遇到的那样。添加另一个唯一约束不是必须的。

“重复密钥”错误告诉您工作没有完成,因为它会生成重复密钥,而不是它发现已经提交给表的重复密钥。

答案 3 :(得分:1)

来自http://www.postgresql.org/docs/current/interactive/datatype.html

注意:在PostgreSQL 7.3之前,序列暗示了UNIQUE。这不再是自动的。如果希望串行列在唯一约束或主键中,则现在必须指定它,与任何其他数据类型相同。

答案 4 :(得分:1)

简介

我也遇到了这个问题,@ adamo提出的解决方案基本上是正确的解决方案。但是,我不得不花很多时间在细节上,这就是为什么我现在写一个新答案以便为其他人节省时间。

案例

我的情况如下:有一个使用应用程序填充数据的表。现在,必须通过SQL手动插入一个新条目。之后,序列不同步,无法通过该应用插入更多记录。

解决方案

如@adamo的答案所述,必须手动同步序列。为此,需要序列名称。对于Postgres,可以使用命令PG_GET_SERIAL_SEQUENCE确定序列的名称。大多数示例使用小写的表名。在我的情况下,这些表是由ORM中间件(例如Hibernate或Entity Framework Core等)创建的,它们的名称都以大写字母开头。

在2004年的一封电子邮件(link)中,我得到了正确的提示。

对于所有示例,假设Foo是表的名称,Foo_id是相关列。

获取序列名称的命令:

SELECT PG_GET_SERIAL_SEQUENCE('"Foo"', 'Foo_id');

因此,表名必须用双引号引起来,并用单引号引起来。

1。验证序列不同步

SELECT CURRVAL(PG_GET_SERIAL_SEQUENCE('"Foo"', 'Foo_id')) AS "Current Value", MAX("Foo_id") AS "Max Value" FROM "Foo";

Current Value小于Max Value时,您的序列不同步。

2。校正

SELECT SETVAL((SELECT PG_GET_SERIAL_SEQUENCE('"Foo"', 'Foo_id')), (SELECT (MAX("Foo_id") + 1) FROM "Foo"), FALSE);

答案 5 :(得分:0)

首先,我认为问题是序列:)。但是错误说 错误:重复的键值违反了唯一约束“ ndxregnum”。因此,我从数据库中查找名称“ ndxregnum”。我在表索引下找到它。然后我删除“ ndxregnum”。然后错误消失了。一切恢复正常。

希望这对您有帮助...

答案 6 :(得分:0)

Referrence - https://www.calazan.com/how-to-reset-the-primary-key-sequence-in-postgresql-with-django/

我遇到了同样的问题,请尝试以下操作: python manage.py sqlsequencereset table_name

例如:

python manage.py sqlsequencereset auth

您需要在生产设置中运行此命令(如果有) 并且您需要安装Postgres才能在服务器上运行

答案 7 :(得分:0)

就我而言,carate 表脚本是:

CREATE TABLE public."Survey_symptom_binds"
(
    id integer NOT NULL DEFAULT nextval('"Survey_symptom_binds_id_seq"'::regclass),
    survey_id integer,
    "order" smallint,
    symptom_id integer,
    CONSTRAINT "Survey_symptom_binds_pkey" PRIMARY KEY (id)
)

所以:

SELECT nextval('"Survey_symptom_binds_id_seq"'::regclass),
       MAX(id) 
  FROM public."Survey_symptom_binds"; 
  
SELECT nextval('"Survey_symptom_binds_id_seq"'::regclass) less than MAX(id) !!!

尝试解决问题:

SELECT setval('"Survey_symptom_binds_id_seq"', (SELECT MAX(id) FROM public."Survey_symptom_binds")+1);

祝大家好运!

答案 8 :(得分:0)

如果表是由 ORM 中间件(如 Hibernate 或 Entity Framework Core 等)创建的,则表名以大写字母开头

SELECT setval('"Table_name_Id_seq"', (SELECT MAX("Id") FROM "Table_name") + 1)
WHERE
    NOT EXISTS (
        SELECT *
        FROM  (SELECT CURRVAL(PG_GET_SERIAL_SEQUENCE('"Table_name"', 'Id')) AS seq, MAX("Id") AS max_id
               FROM "Table_name") AS seq_table
        WHERE seq > max_id
    )

答案 9 :(得分:0)

我遇到了同样的问题。这是因为我的关系类型。我有一个与州和城市相关的表属性。因此,起初我将财产与州的关系设为 OneToOne,对于城市也是如此。我有同样的错误“重复键违反唯一约束”。这意味着:我只能拥有与一个州和城市相关的一项财产。但这没有意义,因为一个城市可以有多个属性。所以问题是关系。关系应该是多对一。一城多房

答案 10 :(得分:0)

用于 Django 的编程解决方案。基于 Paolo Melchiorre's answer,我 wrote a chunk as a function 在任何 .save()

之前被调用
from django.db import connection
def setSqlCursor(db_table):
    sql = """SELECT pg_catalog.setval(pg_get_serial_sequence('"""+db_table+"""', 'id'), MAX(id)) FROM """+db_table+""";"""
    with connection.cursor() as cursor:
        cursor.execute(sql)

答案 11 :(得分:-4)

我有类似的问题,但是我通过删除Postgresql中的所有外键来解决了该问题