修复表结构以避免“错误:重复键值违反唯一约束”

Val*_*spa 16 postgresql database-design insert auto-increment sequence

我有一个以这种方式创建的表:

--
-- Table: #__content
--
CREATE TABLE "jos_content" (
  "id" serial NOT NULL,
  "asset_id" bigint DEFAULT 0 NOT NULL,
   ...
  "xreference" varchar(50) DEFAULT '' NOT NULL,
  PRIMARY KEY ("id")
);
Run Code Online (Sandbox Code Playgroud)

稍后插入一些行并指定 id:

INSERT INTO "jos_content" VALUES (1,36,'About',...)

稍后,一些记录被插入而没有 id 并且它们因错误而失败: Error: duplicate key value violates unique constraint

显然,id 被定义为一个序列:

在此处输入图片说明

每个失败的插入都会增加序列中的指针,直到它增加到一个不再存在的值并且查询成功。

SELECT nextval('jos_content_id_seq'::regclass)

表定义有什么问题?解决这个问题的聪明方法是什么?

Erw*_*ter 23

您的表定义没有问题。
(除了我会使用 hatjos_content_id或其他东西而不是非描述性列名id
我可能会使用text而不是varchar(50).

你的INSERT说法有问题。

id列定义为 时serial,不应为 插入手动值id。这些可能会与相关序列中的下一个值发生冲突。

提供明确的目标列列表(这对于持久化INSERT语句几乎总是一个好主意)并完全省略串行列

INSERT INTO jos_content(asset_id, some_column, ...)
VALUES (36,'About',...);
Run Code Online (Sandbox Code Playgroud)

如果您需要立即自动生成的列的值,请使用RETURNING子句

INSERT ...
RETURNING id;  -- possibly more
Run Code Online (Sandbox Code Playgroud)

有关 SO 的相关答案中的更多详细信息:

如果您在手动输入serial列可能发生冲突后,请将您的序列电流最大值id,以解决一次

SELECT setval('jos_content_id_seq', max(id))
FROM   jos_content;
Run Code Online (Sandbox Code Playgroud)

jos_content_id_seq由 拥有的序列的默认名称在哪里jos_content.id,您已在默认列中找到该名称。似乎是xhzt8_content_id_seq你的情况;


更新: SO 上出现了类似的问题,我想出了一个新的解决方案:

  • @Rodrigo:不在 Postgres 中。上面有更多解释的链接:http://dba.stackexchange.com/a/21496/3684。或者这里。http://dba.stackexchange.com/a/89433/3684 (2认同)