我有一张带有序列号的postgres表。
id (serial) name age插入通常发生在web应用程序中。
我手动插入了两个新记录,将id设置为max (Id)+1*
在这2插入之后,当web应用程序插入2条记录时,它会给出重复的键错误。
只有两张唱片。在那之后一切都很好。
问题是-为什么我的手动插入不增加序列?
自动增量和串行是不同的吗?
我在这里错过了什么?MySQL或任何其他SQL都有相同的问题吗?
发布于 2013-08-22 20:08:03
当您创建一个bigserial列时,PostgreSQL实际上做了三件事:
int或bigint列。nextval()。当您插入一个值而不指定serial列(或者如果您显式指定DEFAULT为其值)时,将对序列调用nextval以:
如果手动为serial列提供一个非默认值,那么序列将不会被更新,nextval可以返回serial列已经使用的值。因此,如果您执行这类操作,则必须通过调用setval手动修复序列。
另外,请记住,可以删除记录,因此serial列中的空白是可以预期的,所以即使没有并发问题,使用max(id) + 1也不是一个好主意。
如果您使用的是serial或bigserial,最好的选择是让PostgreSQL负责为您分配值,并假装它们是不透明的数字,而这些数字恰好是按特定顺序出现的:不要自己分配它们,也不要假设它们是唯一的。这一经验法则适用于所有数据库,海事组织。
我不确定MySQL的auto_increment如何处理所有不同的数据库类型,但也许the fine manual会有所帮助。
发布于 2013-08-22 20:11:13
如果您想要将一条记录插入带有serial列的表中--只需将其从查询中删除--它将自动生成。
或者,您可以使用以下内容插入它的缺陷值:
insert into your_table(id, val)
values (default, '123');第三种选择是不小心直接从串行序列中获取值:
insert into your_table(id, val)
values (nextval(pg_get_serial_sequence('your_table','id')), '123');发布于 2013-08-23 00:57:01
我手动插入了两个新记录,将id设置为max (id)+1**
这种方法是完全错误的,不会在任何数据库中工作。到目前为止,在MySQL中,它只是靠运气才对你起作用的。
如果两个连接同时运行,它们将获得相同的ID。只有在对并发读取锁定表以便每次只能获得一个ID的情况下,它们才能可靠地工作。
这也非常低效。
这就是为什么存在序列,以便在并发插入器存在的情况下可靠地获取is。
只需使用:
INSERT INTO my_table(data1, data2) VALUES ('a','b') RETURNING id;或者:
INSERT INTO my_table(id, data1, data2) VALUES (DEFAULT, 'a','b') RETURNING id;DEFAULT是一个特殊的位置持有者,它告诉数据库从表定义中获取该列的默认值。缺省值是nextval('my_table_id_seq'),因此下一个序列值将被插入。
既然你是在问关于序列的基本问题,我建议你也考虑序列不是无堵塞的。序列有“孔”是正常的,其中表值为1,3,4,5,9,10,.。
https://stackoverflow.com/questions/18389537
复制相似问题