全部產品
Search
文件中心

PolarDB:序列和自動產生列使用指南

更新時間:Sep 20, 2025

在設計資料庫表時,您通常需要一個唯一識別碼作為主鍵,例如使用者ID、訂單號等。手動管理這些ID既繁瑣又容易出錯。為瞭解決這一問題,PolarDB PostgreSQL版(相容Oracle)提供了序列自動產生列兩種機制。它們都能自動、安全地產生唯一的數字序列,簡化了主鍵管理,並確保了資料的一致性。

功能簡介

PolarDB PostgreSQL版(相容Oracle)提供了多種產生唯一序列值的方式,以滿足不同情境的需求,並高度相容Oracle資料庫。

  • 傳統序列
    這是一個獨立的資料庫物件,通過CREATE SEQUENCE建立。在插入資料時,您需要通過調用NEXTVAL偽列(例如my_seq.NEXTVAL)顯式地從序列中擷取下一個值並插入到表中。這種方式最靈活,序列和表是解耦的。

  • 自動產生列
    這是Oracle 12c引入的特性,它將序列隱式地與表中的某一資料行繫結。在建立表時,您只需在列定義上添加GENERATED ... AS IDENTITY子句,資料庫就會在插入新行時自動為該列產生值,無需在INSERT語句中顯式處理。這種方式更加便捷,符合現代資料庫的設計趨勢。

自動產生列根據其行為策略,又分為以下三種類型:

  • GENERATED ALWAYS AS IDENTITY:強制自動產生。系統總是為該列產生值,您不能在INSERT語句中為該列提供顯式值,否則會報錯。這種策略最嚴格,能確保ID完全由資料庫控制。

  • GENERATED BY DEFAULT AS IDENTITY:預設自動產生。只有在INSERT語句中未指定該列時,系統才會為其產生值。如果您提供了具體值,系統將使用您提供的值。但如果您顯式提供NULL,則會報錯。

  • GENERATED BY DEFAULT ON NULL AS IDENTITY:預設或在NULL時自動產生。這是最靈活的策略。當INSERT語句中未指定該列,或為該列顯式提供了NULL值時,系統都會自動為其產生值。這種方式在資料移轉或需要混合插入自訂ID和自動產生ID的情境中非常有用。

前提條件

您的PolarDB PostgreSQL版(相容Oracle)叢集的修訂版本需為2.0.14.17.36.0及以上

說明

您可在控制台查看核心小版本號碼,也可以通過SHOW polardb_version;語句查看。如未滿足核心小版本要求,請升級核心小版本

優勢

  • 簡化開發:自動產生列將ID產生的邏輯封裝在表定義中,使INSERT語句更簡潔,無需關心序列的調用。

  • 保證唯一性:由資料庫保證產生的序列值是唯一的,避免了應用程式層產生ID可能導致的衝突。

  • 靈活性強GENERATED BY DEFAULT ON NULL策略兼顧了自動產生和手動指定的雙重需求,特別適合資料匯入和歷史資料移轉等複雜情境。

選型建議

為了協助您更好地選擇,下表對比了不同序列產生方式的特性:

產生方式

手動指定值

顯式插入NULL

靈活性

資料移轉友好度

推薦情境

傳統序列 (SEQUENCE)

支援

支援(列需允許NULL)

最高

與多表共用序列。

強制產生 (GENERATED ALWAYS)

不支援

不適用

最低

嚴格自增,禁止幹預。

預設產生 (GENERATED BY DEFAULT)

支援

不支援(報錯)

允許覆蓋ID,但不允許NULL。

預設或NULL時產生 (GENERATED BY DEFAULT ON NULL)

支援

支援(觸發自動產生)

最高

新應用、資料移轉、混合ID情境。

最佳實務

  • 對於新開發的應用,推薦使用GENERATED BY DEFAULT ON NULL AS IDENTITY,因為它提供了最大的靈活性。

  • 在進行資料移轉或需要匯入包含存量ID的資料時,GENERATED BY DEFAULT ON NULL是理想選擇。

  • 如果業務要求ID必須由資料庫嚴格控制且絕不允許手動幹預,請使用GENERATED ALWAYS AS IDENTITY

  • 在高並發插入情境下,為IDENTITY列或傳統序列設定一個合理的CACHE值(如CACHE 20或更高)可以顯著提升效能。

使用傳統序列(Sequence)

這種方式下,序列和表是兩個獨立的對象。

  1. 建立序列

    首先,使用CREATE SEQUENCE命令建立一個序列對象,並可以自訂其起始值、步長、最大/小值等屬性。

    CREATE SEQUENCE emp_seq
        START WITH 1000       -- 起始值為1000
        INCREMENT BY 1        -- 每次遞增1
        MAXVALUE 9999         -- 最大值為9999
        NOCYCLE               -- 不迴圈
        CACHE 20;             -- 緩衝20個值以提高效能

    參數說明

    • START WITH:起始值。

    • INCREMENT BY:增量步長。

    • MAXVALUE/NOMAXVALUE:最大值。

    • MINVALUE/NOMINVALUE:最小值。

    • CYCLE/NOCYCLE:是否迴圈。

    • CACHE/NOCACHE:緩衝數量。

    • ORDER/NOORDER:是否保證順序。

  2. INSERT語句中使用序列

    在向表中插入資料時,通過調用序列的NEXTVAL偽列來擷取新的ID。

    -- 建立一個使用序列的表
    CREATE TABLE employees (
        emp_id NUMBER(10) PRIMARY KEY,
        emp_name VARCHAR2(50) NOT NULL
    );
    
    -- 插入資料時調用emp_seq.NEXTVAL
    INSERT INTO employees (emp_id, emp_name) VALUES (emp_seq.NEXTVAL, 'John Smith');
    INSERT INTO employees (emp_id, emp_name) VALUES (emp_seq.NEXTVAL, 'Jane Doe');
    
    -- 查詢結果
    SELECT * FROM employees;
    -- emp_id  |  emp_name
    -- --------+------------
    -- 1000    | John Smith
    -- 1001    | Jane Doe
    
  3. 查詢結果

    SELECT * FROM employees;

    返回結果:

     emp_id |  emp_name  
    --------+------------
       1000 | John Smith
       1001 | Jane Doe
    (2 rows)
  4. 管理序列

    您可以查詢user_sequences視圖來查看序列的目前狀態,或使用ALTER SEQUENCE修改其屬性。

    -- 查看序列的當前值(需要先調用一次NEXTVAL)
    SELECT emp_seq.CURRVAL FROM dual;
    
    -- 修改序列的步長和緩衝
    ALTER SEQUENCE emp_seq INCREMENT BY 2 CACHE 50;

使用自動產生列(Identity Column)

這種方式將序列與表列直接綁定,更為現代化和便捷。

強制產生(GENERATED ALWAYS)

適用於所有ID都應由資料庫嚴格控制的情境。

  1. 建立表:建立一個帶有強制自動產生列的表,並插入資料。

    -- 建立一個帶有強制自動產生列的表
    CREATE TABLE products (
        product_id NUMBER GENERATED ALWAYS AS IDENTITY (
          START WITH 100 
          INCREMENT BY 10
        ),
        product_name VARCHAR2(100) NOT NULL
    );
    
    -- 插入資料時,無需也不能指定product_id列
    INSERT INTO products (product_name) VALUES ('Laptop');
    INSERT INTO products (product_name) VALUES ('Mouse');
  2. 嘗試顯式插入ID

    INSERT INTO products (product_id, product_name) VALUES (999, 'Keyboard');

    返回結果:報錯。

    ERROR:  cannot insert a non-DEFAULT value into column "product_id"
    DETAIL:  Column "product_id" is an identity column defined as GENERATED ALWAYS.
  3. 查詢結果

    SELECT * FROM products ORDER BY product_id;

    返回結果:

     product_id | product_name 
    ------------+--------------
            100 | Laptop
            110 | Mouse
    (2 rows)

預設產生(GENERATED BY DEFAULT)

此方式允許您在需要時覆蓋自動產生的ID,但與ON NULL不同,它不允許顯式插入NULL

  1. 建立表

    CREATE TABLE transactions (
        trans_id NUMBER GENERATED BY DEFAULT AS IDENTITY,
        amount NUMBER(10,2)
    );
  2. 插入方式1:不指定ID,自動產生

    INSERT INTO transactions (amount) VALUES (500.00);
  3. 插入方式2:顯式插入一個自訂。

    INSERT INTO transactions (trans_id, amount) VALUES (9999, 200.00);
  4. 插入方式3:顯式插入NULL將會失敗

    INSERT INTO transactions (trans_id, amount) VALUES (NULL, 150.00);

    返回結果:報錯。

    ERROR:  null value in column "trans_id" of relation "transactions" violates not-null constraint
    DETAIL:  Failing row contains (null, 150).
  5. 查詢結果

    SELECT * FROM transactions ORDER BY trans_id;

    返回結果:

     trans_id | amount 
    ----------+--------
            1 |    500
         9999 |    200
    (2 rows)

預設或在NULL時產生(GENERATED BY DEFAULT ON NULL)

這是最靈活的方式,推薦在新應用和資料移轉情境中使用。

  1. 建立表:建立一個帶有靈活自動產生列的表。

    -- 建立一個帶有靈活自動產生列的表
    CREATE TABLE customers (
        customer_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
        customer_name VARCHAR2(100) NOT NULL
    );
  2. 插入方式1:不指定ID,由資料庫自動產生。

    INSERT INTO customers (customer_name) VALUES ('John Doe');
  3. 插入方式2:顯式插入一個自訂ID(例如,遷移歷史資料)。

    INSERT INTO customers (customer_id, customer_name) VALUES (5000, 'Jane Smith');
  4. 插入方式3:顯式插入NULL,由資料庫自動產生。

    INSERT INTO customers (customer_id, customer_name) VALUES (NULL, 'Bob Wilson');
  5. 查詢結果

    SELECT * FROM customers ORDER BY customer_id;

    返回結果:

     customer_id | customer_name 
    -------------+---------------
               1 | John Doe
               2 | Bob Wilson
            5000 | Jane Smith
    (3 rows)

序列管理與維護

無論是傳統序列還是與自動產生列關聯的內部序列,您都可以對其進行管理和維護。

查看序列資訊

您可以查詢user_sequences視圖來監控所有使用者自訂序列的狀態。

SELECT sequence_name, min_value, max_value, increment_by,
       last_number, cache_size, cycle_flag
FROM user_sequences;

修改序列屬性

使用ALTER SEQUENCE命令可以修改序列的步長、最大值、緩衝大小等屬性。

-- 將emp_seq序列的步長改為2,最大值改為99999,緩衝改為50
ALTER SEQUENCE emp_seq
    START WITH 1005
    INCREMENT BY 2
    MAXVALUE 99999
    CACHE 50;

重設序列

PolarDB PostgreSQL版(相容Oracle)不支援重設序列的命令。標準的做法是刪除並重新建立序列。

-- 刪除現有序列
DROP SEQUENCE emp_seq;

-- 重新建立序列,並設定新的起始值
CREATE SEQUENCE emp_seq START WITH 5000 INCREMENT BY 1;

實際應用情境

在使用者註冊情境中,GENERATED BY DEFAULT ON NULL提供了極大的便利。它既能為新註冊使用者自動產生ID,也允許在資料移轉或大量匯入時指定歷史ID。

  1. 建立使用者賬戶表。

    CREATE TABLE user_accounts (
        user_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY (
            START WITH 100000
            CACHE 100
        ),
        username VARCHAR2(50) UNIQUE NOT NULL,
        email VARCHAR2(100) UNIQUE NOT NULL,
        created_date DATE DEFAULT SYSDATE
    );
  2. 情境1:新使用者正常註冊,自動產生ID。

    INSERT INTO user_accounts (username, email) VALUES ('john_doe', 'john@example.com');
  3. 情境2:從舊系統遷移資料,指定歷史ID。

    INSERT INTO user_accounts (user_id, username, email, created_date) VALUES (99999, 'legacy_user', 'leg***@system.com', DATE '2020-01-01');
  4. 情境3:大量匯入,混合使用自動產生和指定ID。

    INSERT ALL
        INTO user_accounts (username, email) VALUES ('alice', 'ali**@test.com')
        INTO user_accounts (user_id, username, email) VALUES (88888, 'system_acct', 'sys***@app.com')
    SELECT * FROM dual;
  5. 查詢最終結果。

    SELECT * FROM user_accounts ORDER BY user_id;

    返回結果:

     user_id |  username   |       email       |    created_date     
    ---------+-------------+-------------------+---------------------
       88888 | system_acct | sys***@app.com    | 2025-09-17 10:21:38
       99999 | legacy_user | leg***@system.com | 2020-01-01 00:00:00
      100000 | john_doe    | john@example.com  | 2025-09-17 10:21:38
      100001 | alice       | ali**@test.com    | 2025-09-17 10:21:38
    (4 rows)