PostgreSQL中三种自增列sequence,serial,identity区别

总括:使用serial有时不会自增,引起id冲突
         显示插入---插入的时候指定id
         隐式插入---插入的时候不指定id

 

PostgreSQL中三种自增列sequence,serial,identity区别

这三个对象都可以实现自增,这里从如下几个维度来看看这几个对象有哪些不同,其中功能性上看,大部分特性都是一致的或者类似的。

1、sequence在所有数据库中的性质都一样,它是跟具体的字段不是强绑定的,其特点是支持多个对个对象之间共享。

  •  sequence作为自增字段值的时候,对表的写入需要另外单独授权sequence(GRANT USAGE ON SEQUENCE test_old_id_seq;)
  •  sequence类型的字段表,在使用CREATE TABLE new_table LIKE old_table的时候,新表的自增字段会已久指向原始表的sequence

结论:对于自增字段,无特殊需求的情况下,sequence不适合作为“自增列”,作为最最次选。

2、identity本质是为了兼容标准sql中的语法而新加的,修复了一些serial的缺陷,比如无法通过alter table的方式实现增加或者删除serial字段

  •   identity定义成generated by default as identity也允许显式插入,
  •   identity定义成always as identity,加上overriding system value也可以显式不插入

结论:identity是serial的“增强版”,更适合作为“自增列”使用。

3、sequence,serial,identity共同的缺点是在显式插入之后,无法将自增值更新为表中的最大Id,这一点再显式插入的情况下是潜在自增字段Id冲突的
结论:自增列在显式插入之后,一定要手动重置为表的最大Id。

4、自增字段的update没有细看,相对来说自增列的显式插入是一种常规操作,那些对自增列的update操作,只要脑子没问题,一般是不会这么干的。

参考链接:https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/

 

 原始手稿,懒得整理了,不涉及原理性的东西,动手试一遍就明白了。

 
  1. ---------------------------------------------------------sequence-------------------------------------------------------------

  2. create sequence myschema.seq_1 INCREMENT BY 1 MINVALUE 1 START WITH 1;

  3. create table myschema.test_seq

  4. (

  5. id int not null default nextval('myschema.seq_1') primary key,

  6. name varchar(10)

  7. );

  8. 隐式插入

  9. insert into myschema.test_seq (name) values ('aaa');

  10. insert into myschema.test_seq (name) values ('bbb');

  11. insert into myschema.test_seq (name) values ('ccc');

  12.  
  13. select * from myschema.test_seq;

  14.  
  15. 显式插入

  16. insert into myschema.test_seq (id,name) values (5,'ddd');

  17. select * from test_seq;

  18. 再次隐式插入

  19. --可以正常插入

  20. insert into myschema.test_seq (name) values ('eee');

  21. --插入失败,主键重复,因为序列自身是递增的,不会关心表中被显式插入的数据

  22. insert into myschema.test_seq (name) values ('fff');

  23.  
  24. --重置序列的最大值

  25. select setval('myschema.seq_1',(select max(id) from myschema.test_seq)::BIGINT);

  26. --事务回滚后,序列号并不会回滚

  27. begin;

  28. insert into myschema.test_seq (name) values ('ggg');

  29. rollback;

  30.  
  31. -- truncate 表之后,序列不受影响

  32. truncate table myschema.test_seq;

  33. --重置序列

  34. ALTER SEQUENCE myschema.seq_1 RESTART WITH 1;

  35. ---------------------------------------------------------serial-------------------------------------------------------------

  36. create table myschema.test_serial

  37. (

  38. id serial primary key,

  39. name varchar(100)

  40. )

  41.  
  42. select * from test_serial;

  43.  
  44. insert into myschema.test_serial(name) values ('aaa');

  45. insert into myschema.test_serial(name) values ('bbb');

  46. insert into myschema.test_serial(name) values ('ccc');

  47.  
  48. select * from myschema.test_serial;

  49.  
  50. --显式插入,可以执行

  51. insert into myschema.test_serial(id,name) values (5,'ccc');

  52.  
  53. --再次隐式插入,第二次会报错,因为隐式插入的话,serial会基于显式插入之前的Id做自增,serial无法意识到当前已经存在的最大值

  54. insert into myschema.test_serial(name) values ('xxx');

  55. insert into myschema.test_serial(name) values ('yyy');

  56. select * from myschema.test_serial;

  57. --truncate table 后serial不会重置

  58. truncate table myschema.test_serial;

  59.  
  60. insert into myschema.test_serial(name) values ('aaa');

  61. insert into myschema.test_serial(name) values ('bbb');

  62. insert into myschema.test_serial(name) values ('ccc');

  63. select * from myschema.test_serial;

  64. --验证是否会随着事务一起回滚,结论:不会

  65. begin;

  66. insert into myschema.test_serial(name) values ('yyy');

  67. rollback;

  68.  
  69. --重置serial,需要注意的是重置的Id必须要大于相关表的字段最大Id,否则会产生重号

  70. SELECT SETVAL((SELECT pg_get_serial_sequence('myschema.test_serial', 'id')), 1, false);

  71.  
  72.  
  73. ---------------------------------------------------------identity-------------------------------------------------------------

  74. drop table myschema.test_identiy_1

  75.  
  76. create table myschema.test_identiy_1

  77. (

  78. id int generated always as identity (cache 100 START WITH 1 INCREMENT BY 1) primary key ,

  79. name varchar(100)

  80. );

  81.  
  82. create table myschema.test_identiy_2

  83. (

  84. id int generated by default as identity (cache 100 START WITH 1 INCREMENT BY 1) primary key ,

  85. name varchar(100)

  86. );

  87.  
  88.  
  89. insert into myschema.test_identiy_1(name) values ('aaa');

  90. insert into myschema.test_identiy_1(name) values ('bbb');

  91. insert into myschema.test_identiy_1(name) values ('ccc');

  92.  
  93.  
  94. insert into myschema.test_identiy_2(name) values ('aaa');

  95. insert into myschema.test_identiy_2(name) values ('bbb');

  96. insert into myschema.test_identiy_2(name) values ('ccc');

  97.  
  98.  
  99. select * from myschema.test_identiy_1;

  100.  
  101. --显式插入值,如果定义为generated always as identity则不允许显式插入,除非增加overriding system value 提示

  102. --一旦提示了overriding system value,可以

  103. insert into myschema.test_identiy_1(id,name) values (5,'ccc');

  104. insert into myschema.test_identiy_1(id,name)overriding system value values (5,'ccc');

  105. select * from myschema.test_identiy_2;

  106. --显式插入值,如果定义为generated by default as identity则允许显式插入,

  107. insert into myschema.test_identiy_2(id,name) values (5,'ccc');

  108. --显式插入后,继续隐式插入,第二次插入会报错,identity已久是不识别表中显式插入后的最大值

  109. insert into myschema.test_identiy_2(name) values ('xxx');

  110. insert into myschema.test_identiy_2(name) values ('yyy');

  111. select * from myschema.test_identiy_2;

  112.  
  113. 总之个identity很扯淡,你定义成always as identity,加上overriding system value可以显式不插入

  114. 定义成generated by default as identity也允许显式插入

  115. 不管怎么样,既然都允许显式插入,那扯什么淡的来个overriding system value

  116. --truncate后再次插入,自增列不会重置

  117. truncate table myschema.test_identiy_1;

  118. select * from myschema.test_identiy_1;

  119. begin;

  120. insert into myschema.test_identiy_1(name) values ('xxx');

  121. rollback;

  122. --truncate并且RESTART IDENTITY后,会重置自增列

  123. TRUNCATE table myschema.test_identiy_1 RESTART IDENTITY;

  124. select * from myschema.test_identiy_1

  125.  
  126. --identity自增列的重置或者更改

  127. ALTER TABLE myschema.test_identiy_1 ALTER COLUMN id RESTART WITH 100;

 

  •  实际中更改identity自增长列的当前起始值(已有的最大值+1):

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值