我对在下面显示的简单数据库中遇到的一个奇怪的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
答案 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