我在一个简单的数据库中遇到的奇怪的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');
Run Code Online (Sandbox Code Playgroud)
这个问题似乎只发生在新创建的数据库上,一旦发生,它似乎不再发生.我从来没有遇到过这样的事情 - 到目前为止,我刚刚插入了有或没有显式ID和AFAICS的数据,没有任何事情像这样失败......
有谁知道这里发生了什么?!?
环境:Mac OSX 10.7.5上的PostgreSQL 9.1.3
当然这失败了.
怎么了?
创建表时,还会创建一个序列,用于生成ID列的值.序列以1开头,但仅在未指定ID列的值时使用.
现在你跑步的时候
INSERT INTO core.tag(id, title) VALUES (1, 'known tag');
Run Code Online (Sandbox Code Playgroud)
你绕过Postgres自动分配ID值,序列"保持"在一个.
现在你跑步的时候
INSERT INTO core.tag(title) VALUES ('unknown tag');
Run Code Online (Sandbox Code Playgroud)
Postgres从序列中获取下一个值 - 即1.但是该等值存在,因此插入失败.从序列中获取值后,下一个值为2,因此后续插入而未指定ID值将获得2并成功.
解决方案是永远不要在插入中包含ID列.或 - 如果您这样做 - 请求序列中的ID:
INSERT INTO core.tag(id, title) VALUES (nextval('tag_id_seq'), 'known tag');
Run Code Online (Sandbox Code Playgroud)
创建串行列时,它会自动与命名的序列关联<table_name>_<column_name>_seq.这就是我在上述声明中使用的名称.
有关串行"数据类型"如何工作的更多详细信息,请参见手册:http://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-SERIAL
| 归档时间: |
|
| 查看次数: |
351 次 |
| 最近记录: |