简体   繁体   English

Postgres 自增主键

[英]Postgres auto increment primary key

I am trying to work out how an auto increment key is represented in Postgres, depending on whether you create it using the SERIAL type or using an IDENTITY.我正在尝试找出自动增量键在 Postgres 中的表示方式,具体取决于您是使用 SERIAL 类型还是使用 IDENTITY 创建它。

When I create a table with a SERIAL primary key using this DDL:当我使用此 DDL 创建一个带有 SERIAL 主键的表时:

CREATE TABLE public.test_change_column (
    id SERIAL PRIMARY KEY NOT NULL
)

I get a sequence called 'test_change_column_id_seq' and gives the column id a default value of nextval('test_change_column_id_seq'::regclass)我得到一个名为“test_change_column_id_seq”的序列,并为列 id 提供默认值nextval('test_change_column_id_seq'::regclass)

If I create a table without SERIAL and a primary key using this DDL:如果我使用此 DDL 创建一个没有 SERIAL 和主键的表:

CREATE TABLE public.test_change_column (
    id INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY,
)

The creates the sequence but the default value of id is not set to nextval('test_change_column_id_seq'::regclass).创建序列,但 id 的默认值未设置为 nextval('test_change_column_id_seq'::regclass)。 Instead the is_identity column is set to "YES".相反,is_identity 列设置为“YES”。

If you create the column without an autoincrement, you cannot add it at a later stage using the SERIAL:如果您创建的列没有自动增量,则您无法在稍后阶段使用 SERIAL 添加它:

ALTER TABLE public.test_change_column  ALTER COLUMN id TYPE serial; 

this results in the error "type "serial" does not exist".这会导致错误“类型“serial”不存在”。

Using the IDENTITY method, you can add the auto increment using this DDL:使用 IDENTITY 方法,您可以使用此 DDL 添加自动增量:

ALTER TABLE public.test_change_column ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY;

This SQL will show how postgres stores the metadata for the 2 different methods:这个 SQL 将展示 postgres 如何存储两种不同方法的元数据:

SELECT column_name, column_default, is_identity 
FROM information_schema.columns 
WHERE table_name = 'test_change_column';

When it comes removing an auto increment, the auto increment is deleted differently depending on whether you used serial or identity.删除自动增量时,根据您使用的是序列号还是身份,自动增量的删除方式有所不同。

If the auto increment was created using the serial type, you have to ALTER COLUMN id DROP DEFAULT.如果自动增量是使用序列类型创建的,则必须 ALTER COLUMN id DROP DEFAULT。 This does not delete the associated sequence table.这不会删除关联的序列表。

If the auto increment was created using IDENTITY, you have to ALTER COLUMN id DROP IDENTITY.如果自动增量是使用 IDENTITY 创建的,则必须 ALTER COLUMN id DROP IDENTITY。 This also removes the sequence table.这也删除了序列表。

Changing the column to an identity column (and adding the PK constraint) is enough and the correct thing to do (the use of the serial pseudo type is discouraged )将列更改为标识列(并添加 PK 约束)就足够了,而且是正确的做法( 不鼓励使用serial伪类型)

You can see that eg psql reports this correctly as an identity column:您可以看到例如psql将其正确报告为标识列:

arthur=> CREATE TABLE public.test_change_column (id INTEGER NOT NULL);
CREATE TABLE
arthur=> \d public.test_change_column
         Table "public.test_change_column"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           | not null |


arthur=> ALTER TABLE public.test_change_column ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY;
ALTER TABLE
arthur=> ALTER TABLE public.test_change_column ADD CONSTRAINT test_change_column_pkey PRIMARY KEY(id);
ALTER TABLE
arthur=> \d public.test_change_column
                     Table "public.test_change_column"
 Column |  Type   | Collation | Nullable |             Default
--------+---------+-----------+----------+----------------------------------
 id     | integer |           | not null | generated by default as identity
Indexes:
    "test_change_column_pkey" PRIMARY KEY, btree (id)

You can also verify that the default is working by inserting a row:您还可以通过插入一行来验证默认值是否有效:

insert into public.test_change_column default values;

Will create a new row and will increment the id value.将创建一个新行并增加id值。

Such a column will be shown in information_schema.columns with is_identity = 'YES' instead of having a default value.这样的列将显示在information_schema.columns中,其中is_identity = 'YES'而不是默认值。


I recommend to use generated always as identity so that you can't accidentally bypass the generation through the sequence (with the effect that the sequence and the values in the table are no longer "in sync").我建议使用generated always as identity ,这样你就不会意外地通过序列绕过生成(结果是序列和表中的值不再“同步”)。

Create table.创建表。

CREATE TABLE public.test_change_column (
    id INTEGER NOT NULL
);

Alter table in one line:在一行中更改表格:

ALTER TABLE 
    public.test_change_column ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY, 
    ADD CONSTRAINT test_change_column_pkey PRIMARY KEY(id);

\d test_change_column
                     Table "public.test_change_column"
 Column |  Type   | Collation | Nullable |             Default              
--------+---------+-----------+----------+----------------------------------
 id     | integer |           | not null | generated by default as identity
Indexes:
    "test_change_column_pkey" PRIMARY KEY, btree (id)

An IDENTITY column has a sequence associated with it that is used just like with a serial column. IDENTITY列有一个与之关联的序列,就像serial列一样使用。 It is just not shown as the DEFAULT .它只是没有显示为DEFAULT To find underlying sequence:要查找基础序列:

select pg_get_serial_sequence ('public.test_change_column', 'id');
      pg_get_serial_sequence      
----------------------------------
 public.test_change_column_id_seq

select * from public.test_change_column_id_seq ;
 last_value | log_cnt | is_called 
------------+---------+-----------
          1 |       0 | f

You can manipulate the above with the IDENTITY commands here ALTER TABLE :您可以在此处使用ALTER TABLEIDENTITY命令来操作以上内容:

ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | ALTER [COLUMN] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]默认情况下 } 作为身份 [ ( sequence_options ) ]

ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | ALTER [COLUMN] column_name { SET GENERATED { ALWAYS | BY DEFAULT } |默认情况下 } | SET sequence_option |设置序列选项 | RESTART [ [ WITH ] restart ] } [...]重启 [ [ WITH ] 重启 ] } [...]

ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ] ALTER [COLUMN] column_name DROP IDENTITY [IF EXISTS]

UPDATE更新

From here serial type :从这里串行类型

The data types smallserial, serial and bigserial are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases).数据类型 smallserial、serial 和 bigserial 不是真正的类型,而仅仅是创建唯一标识符列的符号方便(类似于其他一些数据库支持的 AUTO_INCREMENT 属性)。 In the current implementation, specifying:在当前的实现中,指定:

CREATE TABLE tablename ( colname SERIAL ); CREATE TABLE 表名(colname SERIAL);

is equivalent to specifying:等同于指定:

CREATE SEQUENCE tablename_colname_seq AS integer;创建序列 tablename_colname_seq AS integer;

CREATE TABLE tablename ( colname integer NOT NULL DEFAULT nextval('tablename_colname_seq') );创建表表名(colname integer NOT NULL DEFAULT nextval('tablename_colname_seq'));

ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname; ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

Thus, we have created an integer column and arranged for its default values to be assigned from a sequence generator.因此,我们创建了一个 integer 列,并安排其默认值从序列生成器分配。 A NOT NULL constraint is applied to ensure that a null value cannot be inserted.应用 NOT NULL 约束以确保无法插入 null 值。 (In most cases you would also want to attach a UNIQUE or PRIMARY KEY constraint to prevent duplicate values from being inserted by accident, but this is not automatic.) Lastly, the sequence is marked as “owned by” the column, so that it will be dropped if the column or table is dropped. (在大多数情况下,您还希望附加一个 UNIQUE 或 PRIMARY KEY 约束以防止意外插入重复值,但这不是自动的。)最后,序列被标记为“由”列拥有,因此它如果列或表被删除,则将被删除。

So if you want to ALTER a table to replicate a serial 'type' you will need to do the individual steps above:因此,如果您想ALTER表以复制serial “类型”,则需要执行上述各个步骤:

CREATE TABLE public.test_change_column (id INTEGER NOT NULL);

create sequence test_change_column_seq;


alter 
    table test_change_column alter COLUMN id 
    set default nextval('test_change_column_seq'), 
ADD CONSTRAINT test_change_column_pkey PRIMARY KEY(id);
alter sequence test_change_column_seq owned by test_change_column.id;

\d test_change_column
                           Table "public.test_change_column"
 Column |  Type   | Collation | Nullable |                   Default                   
--------+---------+-----------+----------+---------------------------------------------
 id     | integer |           | not null | nextval('test_change_column_seq'::regclass)
Indexes:
    "test_change_column_pkey" PRIMARY KEY, btree (id)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM