• 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字段
      2.1 identity定义成generated by default as identity也允许显式插入,
      2.2 identity定义成always as identity,加上overriding system value也可以显式不插入
    结论:identity是serial的“增强版”,更适合作为“自增列”使用。

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

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

     

    复制代码
    ---------------------------------------------------------sequence-------------------------------------------------------------
    create sequence myschema.seq_1 INCREMENT BY 1 MINVALUE 1 START WITH 1;
    create table myschema.test_seq
    (
        id int not null default nextval('myschema.seq_1') primary key,
        name varchar(10)
    );
    隐式插入
    insert into myschema.test_seq (name) values ('aaa');
    insert into myschema.test_seq (name) values ('bbb');
    insert into myschema.test_seq (name) values ('ccc');
    
    select * from myschema.test_seq;
    
    显式插入
    insert into myschema.test_seq (id,name) values (5,'ddd');
    select * from test_seq;
    再次隐式插入
    --可以正常插入
    insert into myschema.test_seq (name) values ('eee');
    --插入失败,主键重复,因为序列自身是递增的,不会关心表中被显式插入的数据
    insert into myschema.test_seq (name) values ('fff');
    
    --重置序列的最大值
    select setval('myschema.seq_1',(select max(id) from myschema.test_seq)::BIGINT);
    --事务回滚后,序列号并不会回滚
    begin;
    insert into myschema.test_seq (name) values ('ggg');
    rollback;
    
    -- truncate 表之后,序列不受影响
    truncate table myschema.test_seq;
    --重置序列
    ALTER SEQUENCE myschema.seq_1 RESTART WITH 1;
    ---------------------------------------------------------serial-------------------------------------------------------------
    create table myschema.test_serial
    (
        id serial primary key,
        name varchar(100)
    )
    
    select * from test_serial;
    
    insert into  myschema.test_serial(name) values ('aaa');
    insert into  myschema.test_serial(name) values ('bbb');
    insert into  myschema.test_serial(name) values ('ccc');
    
    select * from myschema.test_serial;
    
    --显式插入,可以执行
    insert into  myschema.test_serial(id,name) values (5,'ccc');
    
    --再次隐式插入,第二次会报错,因为隐式插入的话,serial会基于显式插入之前的Id做自增,serial无法意识到当前已经存在的最大值
    insert into  myschema.test_serial(name) values ('xxx');
    insert into  myschema.test_serial(name) values ('yyy');
    select * from myschema.test_serial;
    --truncate table 后serial不会重置
    truncate table myschema.test_serial;
    
    insert into  myschema.test_serial(name) values ('aaa');
    insert into  myschema.test_serial(name) values ('bbb');
    insert into  myschema.test_serial(name) values ('ccc');
    select * from myschema.test_serial;
    --验证是否会随着事务一起回滚,结论:不会
    begin;
    insert into  myschema.test_serial(name) values ('yyy');
    rollback;
    
    --重置serial,需要注意的是重置的Id必须要大于相关表的字段最大Id,否则会产生重号
    SELECT SETVAL((SELECT pg_get_serial_sequence('myschema.test_serial', 'id')), 1, false);
    
    
    ---------------------------------------------------------identity-------------------------------------------------------------
    drop table  myschema.test_identiy_1 
    
    create table myschema.test_identiy_1 
    (
        id int generated always as identity (cache 100 START WITH 1 INCREMENT BY 1)  primary key , 
        name varchar(100)
    );
    
    create table myschema.test_identiy_2
    (
        id int generated by default as identity (cache 100 START WITH 1 INCREMENT BY 1)  primary key , 
        name varchar(100)
    );
    
    
    insert into myschema.test_identiy_1(name) values ('aaa');
    insert into myschema.test_identiy_1(name) values ('bbb');
    insert into myschema.test_identiy_1(name) values ('ccc');
    
    
    insert into myschema.test_identiy_2(name) values ('aaa');
    insert into myschema.test_identiy_2(name) values ('bbb');
    insert into myschema.test_identiy_2(name) values ('ccc');
    
    
    select * from myschema.test_identiy_1;
    
    --显式插入值,如果定义为generated always as identity则不允许显式插入,除非增加overriding system value 提示
    --一旦提示了overriding system value,可以
    insert into myschema.test_identiy_1(id,name) values (5,'ccc');
    insert into myschema.test_identiy_1(id,name)overriding system value values (5,'ccc');
    select * from myschema.test_identiy_2;
    --显式插入值,如果定义为generated by default as identity则允许显式插入,
    insert into myschema.test_identiy_2(id,name) values (5,'ccc');
    --显式插入后,继续隐式插入,第二次插入会报错,identity已久是不识别表中显式插入后的最大值
    insert into myschema.test_identiy_2(name) values ('xxx');
    insert into myschema.test_identiy_2(name) values ('yyy');
    select * from myschema.test_identiy_2;
    
    总之个identity很扯淡,你定义成always as identity,加上overriding system value可以显式不插入
    定义成generated by default as identity也允许显式插入
    不管怎么样,既然都允许显式插入,那扯什么淡的来个overriding system value
    --truncate后再次插入,自增列不会重置
    truncate table myschema.test_identiy_1;
    select * from myschema.test_identiy_1;
    begin;
    insert into myschema.test_identiy_1(name) values ('xxx');
    rollback;
    --truncate并且RESTART IDENTITY后,会重置自增列
    TRUNCATE table myschema.test_identiy_1 RESTART IDENTITY;
    select * from myschema.test_identiy_1
    
    --identity自增列的重置表或者更改
    ALTER TABLE myschema.test_identiy_1 ALTER COLUMN id RESTART WITH 100;



    PostgreSQL SERIAL伪类型
    PostgreSQL序列是一种特殊的用于生产整数序列数据库对象。序列通常用于主键列,与mysql的AUTO_INCREMENT 概念类似。创建表时使用serial伪类型定义序列:

    CREATE TABLE table_name(
    id SERIAL
    );
    1
    2
    3
    赋值serial伪类型给id列,PostgreSQL将执行下列步骤:

    创建序列对象并设置下一个生成值作为列的缺省值。
    给对应列增加NOT NULL约束,因为序列总是生成一个整数值,不能为null值。
    赋值序列的拥有者给id列,因此当id列或表被删除时,序列对象自动被删除。
    对应背后执行语句:

    CREATE TABLE table_name(
    id SERIAL
    );
    1
    2
    3
    相当于执行了下面语句:

    CREATE SEQUENCE table_name_id_seq;

    CREATE TABLE table_name (
    id integer NOT NULL DEFAULT nextval('table_name_id_seq')
    );

    ALTER SEQUENCE table_name_id_seq
    OWNED BY table_name.id;




    螃蟹在剥我的壳,笔记本在写我,漫天的我落在枫叶上雪花上,而你在想我。 --章怀柔
  • 相关阅读:
    你知道线框图和原型有啥区别吗
    Git 创建与合并分支
    Java 多态 接口继承等学习笔记
    JAVA多线程之生产者 消费者模式 妈妈做面包案例
    Robot Framework自动化测试(一)---第一个脚本
    仲夏之夜
    vulstack红队评估(一)
    CVE-2017-7269-iis远程溢出漏洞复现
    JMeter 控件整理
    JMeter函数整理
  • 原文地址:https://www.cnblogs.com/lovezhr/p/14992207.html
Copyright © 2020-2023  润新知