PostgreSQL:琐碎的INSERT第一次失败,之后成功

时间:2013-01-11 08:46:50

标签: postgresql insert

我对在下面显示的简单数据库中遇到的一个奇怪的Postgres问题感到困惑:如果我首先插入标记并明确指定其ID,然后尝试插入另一个标记而不用传递ID,然后第二次插入失败。如果我第三次尝试(再次没有ID),插入成功。

DROP DATABASE IF EXISTS mydb;
CREATE DATABASE mydb;

\c mydb

DROP SCHEMA public;
CREATE SCHEMA core;

CREATE TABLE core.tag
(
    id serial PRIMARY KEY,
    title text NOT NULL
);

-- this works: all columns specified explicitly
INSERT INTO core.tag(id, title) VALUES (1, 'known tag');

-- omitting the tag ID fails with
-- ERROR:  duplicate key value violates unique constraint "tag_pkey"
-- DETAIL:  Key (id)=(1) already exists.
INSERT INTO core.tag(title) VALUES ('unknown tag');

-- this works again ?!?
INSERT INTO core.tag(title) VALUES ('unknown tag');

问题似乎只发生在新创建的数据库上,一旦发生,它似乎不再发生。我从未遇到过这样的事情 - 到目前为止,我刚刚插入了有或没有显式ID和AFAICS的数据,没有任何事情像这样失败......

有谁知道这里发生了什么?!?

环境:Mac OSX 10.7.5上的PostgreSQL 9.1.3

1 个答案:

答案 0 :(得分:6)

当然这失败了。

会发生什么?

创建表时,还会创建一个序列,用于生成ID列的值。序列以1开头,但仅在为ID列指定值时使用。

现在运行

INSERT INTO core.tag(id, title) VALUES (1, 'known tag');

你绕过Postgres'自动分配ID值,顺序"停留"在一个。

现在运行

INSERT INTO core.tag(title) VALUES ('unknown tag');

Postgres从序列中获取下一个值 - 即1.但是该等值存在,因此插入失败。从序列中获取值后,下一个值为2,因此后续插入而未指定ID值将获得2并成功。

解决方案是永远不要在插入中包含ID列。或 - 如果您这样做 - 请从序列中请求ID:

INSERT INTO core.tag(id, title) VALUES (nextval('tag_id_seq'), 'known tag');

创建串行列时,它会自动与名为<table_name>_<column_name>_seq的序列关联。这就是我在上述陈述中使用的名称。

有关串行&#34;数据类型&#34;的详细信息。作品在手册中:http://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-SERIAL