1. ホーム
  2. データベース
  3. ポストグレスキュー

PostgreSQLにおけるsequence、serial、identityの使い方の違いについて

2022-01-19 02:40:23

これら3つのオブジェクトは、いずれも自己増殖が可能です。ここでは、以下の次元での違いを見ていきますが、そのほとんどは機能的に一貫しているか、または類似しています。

<イグ

1、配列はどのデータベースでも同じであること、特定のフィールドに強く束縛されないこと、複数のオブジェクトのペア間の共有をサポートすることが特徴である。

シーケンスを自己インクリメントのフィールド値として使用する場合、テーブルへの書き込みにはシーケンスに対する個別の認証が必要です(GRANT USAGE ON SEQUENCE test_old_id_seq;)。

シーケンス型フィールドのテーブルで、CREATE TABLE new_table LIKE old_table を使用すると、新しいテーブルのセルフインクリメントフィールドはすでに元のテーブルのシーケンスを指すことになります。

おわりに

自己インクリメントのフィールドに対して、シーケンスは特に必要性がなければ "自己インクリメントカラム" として適切ではなく、最も好ましくない選択肢です。

2. IDは基本的に標準SQL構文に新しく追加されたもので、alter tableによるシリアルフィールドの追加や削除ができないといったシリアルの欠点を修正したものです。

2.1 IDはデフォルトで生成されると定義されている IDは、明示的に挿入することも可能であるため

2.2 IDは常にIDとして定義され、さらにシステム値を上書きすることで明示的な非挿入を可能にする。

おわりに

identityはserialのquot;enhanced"バージョンで、self-incrementing column"として使うのにより適している。

3. シーケンス、シリアル、アイデンティティの共通の欠点は、明示的な挿入の後、自己インクリメントをテーブルの最大Idまで更新できないことで、明示的な挿入の場合、自己インクリメントフィールドIdの衝突の可能性があることである

おわりに

セルフインクリメントカラムは、明示的な挿入の後、常にテーブルの最大Idに手動でリセットする必要があります。

4は、自己増分フィールドの更新が密接に見ていない、比較的、自己増分カラムの明示的な挿入は、ルーチン操作、自己増分カラムのそれらの更新操作、限り、脳が間違っていないように、通常はそうしないようにされています。

元の原稿は、整理するのが面倒、物事の原則に関与していない、一度試してみて、あなたは理解するでしょう。

---------------------------------------------------------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)
);
Implicit insertion
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;
Explicit Insert
insert into myschema.test_seq (id,name) values (5,'ddd');
select * from test_seq;
Implicit insert again
-- can insert normally
insert into myschema.test_seq (name) values ('eee');
--insert fails with duplicate primary key because the sequence itself is incremental and doesn't care about the data being inserted explicitly in the table
insert into myschema.test_seq (name) values ('fff');
--reset the maximum value of the sequence
select setval('myschema.seq_1',(select max(id) from myschema.test_seq)::BIGINT);
-- The sequence number is not rolled back after the transaction is rolled back
begin;
insert into myschema.test_seq (name) values ('ggg');
rollback;
-- After truncate table, the sequence is not affected
truncate table myschema.test_seq;
--reset the sequence
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;
-- explicit insert, can be executed
insert into myschema.test_serial(id,name) values (5,'ccc');
--implicit insert again, the second time will report an error, because if implicitly inserted, serial will do self-increment based on the Id before the explicit insert, and serial will not be aware of the maximum value that currently exists
insert into myschema.test_serial(name) values ('xxx');
insert into myschema.test_serial(name) values ('yyy');
select * from myschema.test_serial;
--truncate table after serial will not reset
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;
--Verify if the transaction will be rolled back with the transaction, conclusion: no
begin;
insert into myschema.test_serial(name) values ('yyyy');
rollback;
--reset serial, it should be noted that the reset Id must be greater than the maximum Id of the relevant table field, otherwise it will generate a duplicate number
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;
--Explicit insertion of values, if defined as generated always as identity then explicit insertion is not allowed unless overriding system value is added
-- Once prompted for the overriding system value, you can
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;
-- explicitly insert values, if defined as generated by default as identity then explicit insertion is allowed.
insert into myschema.test_identiy_2(id,name) values (5,'ccc');
-- After the explicit insertion, continue the implicit insertion, the second insertion will report an error, identity has long been the maximum value after the explicit insertion in the table is not recognized
insert into myschema.test_identiy_2(name) values ('xxx');
insert into myschema.test_identiy_2(name) values ('yyy');
select * from myschema.test_identiy_2;
In short an identity is bullshit, you define it as always as identity, plus overriding system value can be explicitly not inserted
Defined as generated by default as identity also allows explicit insertion
Anyway, since it allows explicit insertion, what's the point of overriding system value?
--truncate and insert again, the self-incremented column will not be reset
truncate table myschema.test_identiy_1;
select * from myschema.test_identiy_1;
begin;
insert into myschema.test_identiy_1(name) values ('xxx');
rollback;
--truncate and reset the self-incrementing column after RESTART IDENTITY
TRUNCATE table myschema.test_identiy_1 RESTART IDENTITY;
select * from myschema.test_identiy_1
--identity self-incrementing table or change
ALTER TABLE myschema.test_identiy_1 ALTER COLUMN id RESTART WITH 100;

実際には、ID自己成長カラムの現在の開始値(既存の最大値+1)を変更します。

追記 PostgreSQL はテーブルごとに異なるセルフインクリメントシーケンスを使用します。

hibernateの設定ファイルは以下のようなものです。

<id name="id">
  <generator class="sequence">
  <param name="sequence">adminuser</param>
  </generator>
 </id>

xdocletを使用する場合、クラス内の設定は以下のようになります。