嗨我有一个问题,我知道这次发布很多次,但我找不到问题的答案。问题是我有一个表和一列“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)
是否应该采取或是否还有其他事情要做?
答案 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');
因此,表名必须用双引号引起来,并用单引号引起来。
SELECT CURRVAL(PG_GET_SERIAL_SEQUENCE('"Foo"', 'Foo_id')) AS "Current Value", MAX("Foo_id") AS "Max Value" FROM "Foo";
当Current Value
小于Max Value
时,您的序列不同步。
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)
我遇到了同样的问题,请尝试以下操作:
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中的所有外键来解决了该问题