Postgresql

什麼是身份列?

  • April 30, 2018

我正在查看7/01 為 PostgreSQL 安排的 commit-fest,我看到 Pg 可能很快就會獲得“身份列”。

我在information_schema.columns中發現了一些提及,但沒什麼

is_identity         yes_or_no         Applies to a feature not available in PostgreSQL
identity_generation character_data    Applies to a feature not available in PostgreSQL
identity_start      character_data    Applies to a feature not available in PostgreSQL
identity_increment  character_data    Applies to a feature not available in PostgreSQL
identity_maximum    character_data    Applies to a feature not available in PostgreSQL
identity_minimum    character_data    Applies to a feature not available in PostgreSQL
identity_cycle      yes_or_no         Applies to a feature not available in PostgreSQL

維基百科頁面也沒有說太多

標識列與主鍵的不同之處在於它的值由伺服器管理並且通常無法修改。在許多情況下,標識列用作主鍵;然而,這並非總是如此。

但是,我在他們身上看不到其他任何東西。身份列如何工作?它們是否提供了任何新功能,或者這只是創建序列的標準方法?新功能的任何故障以及它是如何工作的?

它們是如何在 PG 10 中實際實現的

您可以使用測試套件的預期輸出來查看它們現在是如何實際實現的。

一些關鍵可以擺脫這個。

  • 您可以使用創建表的子句或通過指定從哪裡開始以及跳過多少ALTER TABLESTART 7 INCREMENT BY 5
  • 插入到具有標識列的表中現在可以OVERRIDING USER VALUE用於強制替換衝突行的標識列:
INSERT INTO t OVERRIDING USER VALUE VALUES (10, 'xyz');

-- this isn't currently allowed.
CREATE TABLE t ( a serial PRIMARY KEY, b text );
INSERT INTO t (a,b) VALUES (1,'foo');
INSERT INTO t (a,b) VALUES (1,'bar');
  • 您可以指定GENERATED ALWAYS以確保生成,然後您只需要OVERRIDING SYSTEM VALUE忽略它,否則當您INSERT為標識列指定值的行時會出現錯誤。
ERROR:  cannot insert into column "a"
DETAIL:  Column "a" is an identity column defined as GENERATED ALWAYS.
HINT:  Use OVERRIDING SYSTEM VALUE to override.
  • 標識列必須是NOT NULL
  • 權限從表傳播,沒有更多的底層序列。
  • 身份可以在不同的點完全重置RESTART

您可以在 PostgreSQL 10 文件中閱讀有關這些的更多資訊

ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ]
ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...]
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]

這是為了實現標準中的功能。(抄自草稿,日期:2011-12-21):

4.15.11標識列

基表 BT 的列可以選擇性地包括不超過一個標識列。例如,標識列的聲明類型要麼是比例為 0(零)的精確數字類型INTEGER,要麼是其源類型是比例為 0(零)的精確數字類型的獨特類型。標識列具有起始值、增量、最大值、最小值和循環選項。

… 標識列的定義可以指定GENERATED ALWAYSGENERATED BY DEFAULT

它是一個**列的屬性,**它基本上表示該列的值將由 DBMS 而不是由使用者提供,並且以某種特定的方式和限制(增加、減少、具有最大/最小值、如果最大/達到最小值)。

序列生成器(通常稱為“序列”)是一個相關的 SQL 標準特性:它是一種提供此類值的機制 - 並且可用於標識列。

請注意細微差別:aSEQUENCE是一個對象,可用於為一個或多個標識列提供值,甚至可以隨意提供值。


到目前為止,各種 DBMS 以不同的方式和語法(MySQL:AUTO_INCREMENT、SQL Server:IDENTITY (seed, increment)、PostgreSQL:serial使用SEQUENCE、Oracle:使用觸發器等)實現了類似的功能,並且僅在最近添加了序列生成器(2012 版中的 SQL Server 和 12c 中的 Oracle) .

到目前為止,Postgres 已經實現了序列生成器(可用於為列提供值,可以使用特殊宏serial或函式) bigserialnextval()但尚未實現標識列的語法,因為它在標準中。

從 SQL 標准定義標識列(以及與列的細微差別serial)和各種語法(例如GENERATED ALWAYSNEXT VALUE FOR等)是該特性的意義所在。可能還需要對序列的實現進行一些更改/改進,因為標識列將使用序列。

如果您按照連結身份列(從您看到的頁面),您會發現:

標識列

發件人:Peter Eisentraut

收件人:pgsql-hackers 主題:身份列

日期:2016-08-31 04:00:42

郵件 ID:6adbacbf-73bc-dd1a-2033-63409180fd18@2ndquadrant.com


這是實現標識列的另一種嘗試。這是 PostgreSQL 串列列的一個符合標準的變體。它還修復了串列列存在的一些可用性問題:

  • 除了表(*)之外,還需要對序列設置權限
  • CREATE TABLE/LIKE複製預設值但引用相同的序列
  • 無法添加/刪除序列性ALTER TABLE
  • 刪除預設不刪除序列
  • 輕微的怪異,因為串列是某種特殊的宏

(*) 還沒有真正實現,因為我想利用 NEXT VALUE FOR我之前發布的東西,但我還有更多的工作要做。

**2017 年 9 月更新:**似乎該功能將出現在 Postgres 10 中,該功能將在幾天/幾週內發布: Postgres 10 中的新增功能:身份列


Oracle 還在版本 12c 中實現了標識列和序列。據我檢查,語法符合標準:

Oracle Database 12c Release 1 (12.1) 中的標識列

12c 數據庫引入了針對使用數字類型定義的表列定義標識子句的能力。語法如下所示。

GENERATED
[ ALWAYS | BY DEFAULT [ ON NULL ] ]
AS IDENTITY [ ( identity_options ) ]

引用自:https://dba.stackexchange.com/questions/158988