代码之家  ›  专栏  ›  技术社区  ›  Ian Baget

PostgreSQL自动增量

  •  513
  • Ian Baget  · 技术社区  · 16 年前

    INT 列与 AUTO INCREMENT 我在PostgreSQL文档中看到了一个名为 SERIAL

    9 回复  |  直到 10 年前
        1
  •  759
  •   yakirchi Trey    4 年前

    是的,SERIAL是等效函数。

    CREATE TABLE foo (
        id SERIAL,
        bar varchar
    );
    
    INSERT INTO foo (bar) VALUES ('blah');
    INSERT INTO foo (bar) VALUES ('blah');
    
    SELECT * FROM foo;
    
    +----------+
    | 1 | blah |
    +----------+
    | 2 | blah |
    +----------+
    

    SERIAL只是一个围绕序列创建表时宏。您不能在现有列上更改SERIAL。

        2
  •  244
  •   user272735    13 年前

    您可以使用任何其他 integer data type ,例如 smallint .

    例子:

    CREATE SEQUENCE user_id_seq;
    CREATE TABLE user (
        user_id smallint NOT NULL DEFAULT nextval('user_id_seq')
    );
    ALTER SEQUENCE user_id_seq OWNED BY user.user_id;
    

    最好使用自己的数据类型,而不是用户 serial data type .

        3
  •  116
  •   Felipe    12 年前

    如果你想在已经存在的表中的id中添加序列,你可以使用:

    CREATE SEQUENCE user_id_seq;
    ALTER TABLE user ALTER user_id SET DEFAULT NEXTVAL('user_id_seq');
    
        4
  •  55
  •   Programster    9 年前

    从Postgres 10开始,也支持SQL标准定义的标识列:

    create table foo 
    (
      id integer generated always as identity
    );
    

    创建一个标识列,除非明确要求,否则该列不能被覆盖。以下插入将失败,列定义为 generated always :

    insert into foo (id) 
    values (1);
    

    然而,这可以被推翻:

    insert into foo (id) overriding system value 
    values (1);
    

    generated by default serial 实施:

    create table foo 
    (
      id integer generated by default as identity
    );
    

    当手动提供值时,也需要手动调整基础序列,这与使用 串行 列。


    默认情况下,标识列不是主键(就像 串行 列)。如果应该是主键约束,则需要手动定义主键约束。

        5
  •  54
  •   a_horse_with_no_name    7 年前

    虽然看起来序列是 MySQL auto_increment有一些微妙但重要的区别:

    1.失败的查询会增加序列/序列

    序列列在查询失败时递增。这会导致失败查询的碎片化,而不仅仅是行删除。例如,在PostgreSQL数据库上运行以下查询:

    CREATE TABLE table1 (
      uid serial NOT NULL PRIMARY KEY,
      col_b integer NOT NULL,
      CHECK (col_b>=0)
    );
    
    INSERT INTO table1 (col_b) VALUES(1);
    INSERT INTO table1 (col_b) VALUES(-1);
    INSERT INTO table1 (col_b) VALUES(2);
    
    SELECT * FROM table1;
    

    您应该得到以下输出:

     uid | col_b 
    -----+-------
       1 |     1
       3 |     2
    (2 rows)
    

    请注意uid是如何从1到3而不是从1到2的。

    如果您使用以下命令手动创建自己的序列,仍然会发生这种情况:

    CREATE SEQUENCE table1_seq;
    CREATE TABLE table1 (
        col_a smallint NOT NULL DEFAULT nextval('table1_seq'),
        col_b integer NOT NULL,
        CHECK (col_b>=0)
    );
    ALTER SEQUENCE table1_seq OWNED BY table1.col_a;
    

    如果你想测试MySQL的不同之处,请在MySQL数据库上运行以下命令:

    CREATE TABLE table1 (
      uid int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
      col_b int unsigned NOT NULL
    );
    
    INSERT INTO table1 (col_b) VALUES(1);
    INSERT INTO table1 (col_b) VALUES(-1);
    INSERT INTO table1 (col_b) VALUES(2);
    

    你应该得到以下内容 无碎片化 :

    +-----+-------+
    | uid | col_b |
    +-----+-------+
    |   1 |     1 |
    |   2 |     2 |
    +-----+-------+
    2 rows in set (0.00 sec)
    

    2.手动设置串行列值可能会导致未来的查询失败。

    @trev在之前的回答中指出了这一点。

    要模拟此情况,请手动将uid设置为4,稍后将“碰撞”。

    INSERT INTO table1 (uid, col_b) VALUES(5, 5);
    

    表格数据:

     uid | col_b 
    -----+-------
       1 |     1
       3 |     2
       5 |     5
    (3 rows)
    

    运行另一个插入:

    INSERT INTO table1 (col_b) VALUES(6);
    

    表格数据:

     uid | col_b 
    -----+-------
       1 |     1
       3 |     2
       5 |     5
       4 |     6
    

    现在,如果你运行另一个插入:

    INSERT INTO table1 (col_b) VALUES(7);
    

    它将失败,并显示以下错误消息:

    错误:重复的键值违反了唯一约束“table1_pkey”

    相比之下,MySQL将优雅地处理这个问题,如下所示:

    INSERT INTO table1 (uid, col_b) VALUES(4, 4);
    

    INSERT INTO table1 (col_b) VALUES(3);
    

    +-----+-------+
    | uid | col_b |
    +-----+-------+
    |   1 |     1 |
    |   2 |     2 |
    |   4 |     4 |
    |   5 |     3 |
    +-----+-------+
    

    测试是在MySQL 5.6.33、Linux(x86_64)和PostgreSQL 9.4.9上进行的

        6
  •  36
  •   Zhao Li    7 年前

    抱歉,重复一个旧问题,但这是谷歌上弹出的第一个Stack Overflow问题/答案。

    这篇文章(首先在谷歌上出现)讨论了PostgreSQL 10使用更新的语法: https://blog.2ndquadrant.com/postgresql-10-identity-columns/

    这恰好是:

    CREATE TABLE test_new (
        id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    );
    

    希望有帮助:)

        7
  •  17
  •   trev    12 年前

    您必须小心不要直接插入到SERIAL或序列字段中,否则当序列达到插入值时,您的写入将失败:

    -- Table: "test"
    
    -- DROP TABLE test;
    
    CREATE TABLE test
    (
      "ID" SERIAL,
      "Rank" integer NOT NULL,
      "GermanHeadword" "text" [] NOT NULL,
      "PartOfSpeech" "text" NOT NULL,
      "ExampleSentence" "text" NOT NULL,
      "EnglishGloss" "text"[] NOT NULL,
      CONSTRAINT "PKey" PRIMARY KEY ("ID", "Rank")
    )
    WITH (
      OIDS=FALSE
    );
    -- ALTER TABLE test OWNER TO postgres;
     INSERT INTO test("Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss")
               VALUES (1, '{"der", "die", "das", "den", "dem", "des"}', 'art', 'Der Mann küsst die Frau und das Kind schaut zu', '{"the", "of the" }');
    
    
     INSERT INTO test("ID", "Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss")
               VALUES (2, 1, '{"der", "die", "das"}', 'pron', 'Das ist mein Fahrrad', '{"that", "those"}');
    
     INSERT INTO test("Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss")
               VALUES (1, '{"der", "die", "das"}', 'pron', 'Die Frau, die nebenen wohnt, heißt Renate', '{"that", "who"}');
    
    SELECT * from test; 
    
        8
  •  15
  •   Prince    10 年前

    在所提问题的背景下,并回应@sereja1c的评论,创建 SERIAL 隐式创建序列,因此对于上述示例-

    CREATE TABLE foo (id SERIAL,bar varchar);
    

    CREATE TABLE 将隐式创建序列 foo_id_seq 用于串行列 foo.id 因此, 串行 [4 Bytes]易于使用,除非您的id需要特定的数据类型。

        9
  •  8
  •   Sergey Vishnevetskiy    6 年前

    自从PostgreSQL 10

    CREATE TABLE test_new (
        id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
        payload text
    );
    
        10
  •  5
  •   webtechnelson    7 年前

    这种方法肯定会奏效,我希望它能有所帮助:

    CREATE TABLE fruits(
       id SERIAL PRIMARY KEY,
       name VARCHAR NOT NULL
    );
    
    INSERT INTO fruits(id,name) VALUES(DEFAULT,'apple');
    
    or
    
    INSERT INTO fruits VALUES(DEFAULT,'apple');
    

    您可以在下一个链接中查看详细信息: http://www.postgresqltutorial.com/postgresql-serial/

        11
  •  3
  •   user9802313 user9802313    5 年前

    创建序列。

    CREATE SEQUENCE user_role_id_seq
      INCREMENT 1
      MINVALUE 1
      MAXVALUE 9223372036854775807
      START 3
      CACHE 1;
    ALTER TABLE user_role_id_seq
      OWNER TO postgres;
    

    并更改表格

    ALTER TABLE user_roles ALTER COLUMN user_role_id SET DEFAULT nextval('user_role_id_seq'::regclass);