全部產品
Search
文件中心

Hologres:產生列

更新時間:Jan 15, 2026

產生列(Generated Columns)是由其他列計算得到的特殊的列,分為儲存產生列(Stored Generated Columns)和虛擬產生列(Virtual Generated Columns)。從Hologres V3.1版本開始,支援儲存產生列,即在資料寫入或更新時自動進行計算,並實際佔用儲存空間。目前暫不支援虛擬產生列。本文為您介紹Hologres中儲存產生列的使用方法。

使用情境

  • 實現對所需欄位的自動計算:消除手動處理計算邏輯的業務需求。

  • 保障資料的一致性:避免人為操作或代碼邏輯的錯誤,而導致資料不一致。

  • 最佳化查詢效能:對於高頻查詢的情境,儲存產生列的讀取等同於普通列。

  • 簡化商務邏輯:對於固定常用資料轉換操作,能夠降低SQL複雜度。

根據您的業務需要,合理使用產生列能顯著提升開發效率並保障資料的可靠性。

文法

通過GENERATED ALWAYS AS子句聲明產生列,並通過STORED關鍵字來指定儲存產生列。

  • 建立包含產生列的表。

    CREATE TABLE generated_col_t (
        [...,]
        col1 INT,
        col2 INT GENERATED ALWAYS AS (col1 + 1) STORED
    );
  • 建立包含產生列的邏輯分區表,並將產生列作為分區鍵。

    CREATE TABLE generated_col_logical_part (
        a TEXT,
        b INT,
        ts TIMESTAMP NOT NULL,
        d TIMESTAMP GENERATED ALWAYS AS (date_trunc('day', ts)) STORED NOT NULL
    )
    LOGICAL PARTITION BY LIST(d);

注意事項

  • CREATE TABLE時

    • 定義產生列時,只支援使用IMMUTABLE的函數或運算式,不支援非IMMUTABLE函數,如CURRENT_DATE、RANDOM等。

    • 定義產生列時,運算式不支援引用其他產生列,不支援對產生列定義default關鍵字。

    • 建立分區表時,支援將邏輯分區表的分區鍵設為產生列,不支援將物理分區表的分區鍵設為產生列。而分區表中的普通列均支援設為產生列。

    • 建立外部表格(CREATE FOREIGN TABLE)時,不支援定義產生列。

    • 支援將產生列設為Hologres各類索引,包括主鍵、分布鍵、分段鍵、聚簇索引、位元影像索引和字典編碼列。

  • ALTER TABLE時

    • 不支援ADD的Column為產生列。

    • 支援DROP產生列。但在產生列未被DROP之前,不支援DROP該產生列的引用列。

    • 不支援修改產生列的資料類型,不支援修改產生列引用列的資料類型。建議您通過REBUILD功能實現,詳情請參見REBUILD

    • 支援RENAME產生列列名。

  • DML/DQL時

    • 資料寫入或更新含產生列的表時,允許不指定產生列或使用default關鍵字,但不支援指定產生列直接寫入。

    • 資料更新時,如果產生列或其引用的列是分布鍵(distribution_key),則不支援更新該列。

    • 通過Fixed Plan進行資料更新時,如果主鍵為產生列,則不支援更新產生列的引用列。

    • 通過Fixed Plan進行部分列更新時,如果產生的列引用多個普通列,則不支援只更新其中的部分列。

    • 其他方式的操作均支援包含產生列的表,包括通過HQE引擎執行的讀寫、通過Fixed Plan執行的讀寫以及Copy等方式。

  • 其他動作

    • CREATE TABLE LIKE建立時,支援原表有產生列,需開啟hg_experimental_enable_create_table_like_properties參數,以保留產生列屬性。

    • CREATE TABLE AS建立時,不支援原表有產生列。

    • 如需修改包含產生列的表的參數,支援通過REBUILD文法(含遷移表的Table Group),請參見REBUILD。不支援使用HG_MOVE_TABLE_TO_TABLE_GROUP文法遷移表的Table Group。

    • 如需對包含產生列的表執行INSERT OVERWRITE操作,Hologres V3.1版本支援原生INSERT OVERWRITE文法。不支援原hg_insert_overwrite文法,詳情請參見該文法的INSERT OVERWRITE

使用樣本

  1. 建立帶有產生列的表。

    CREATE TABLE generated_col_t (
        id INT PRIMARY KEY,
        col1 INT,
        col2 INT GENERATED ALWAYS AS (col1 + 1) STORED
    );
  2. 資料匯入。

    • 支援資料匯入全部非產生列。樣本如下:

      INSERT INTO generated_col_t VALUES (1, 1);
      INSERT INTO generated_col_t(id, col1) VALUES (2, 2);

      通過查詢命令SELECT * FROM generated_col_t;顯示結果如下。

      id	col1	col2
      1	1	2
      2	2	3
    • 支援資料匯入時對產生列使用default關鍵字。樣本如下:

      INSERT INTO generated_col_t VALUES (3, 3, default);
      INSERT INTO generated_col_t(id, col1, col2) VALUES (4, 4, default);

      通過查詢命令SELECT * FROM generated_col_t;顯示結果如下。

      id	col1	col2
      4	4	5
      2	2	3
      3	3	4
      1	1	2
    • 不支援對指定產生列進行匯入。樣本如下:

      INSERT INTO generated_col_t VALUES (5, 5, 6);
      INSERT INTO generated_col_t(id, col1, col2) VALUES (6, 6, 7);

      返回結果如下。

      a1 - 副本

  3. 資料更新。

    • 支援更新非產生列資料。樣本如下:

      UPDATE generated_col_t SET col1 = 2 WHERE id = 1;

      通過查詢命令SELECT * FROM generated_col_t;顯示結果如下。

      id	col1	col2
      2	2	3
      3	3	4
      4	4	5
      1	2	3     -- 該列資料已發生變化 
    • 支援更新資料時對產生列使用default關鍵字。樣本如下:

      UPDATE generated_col_t SET col1 = 3, col2 = default WHERE id = 2;

      通過查詢命令SELECT * FROM generated_col_t;顯示結果如下。

      id	col1	col2
      3	3	4
      2	3	4    -- 該列資料已發生變化
      4	4	5
      1	2	3
    • 不支援對指定產生列進行更新。樣本如下:

      UPDATE generated_col_t SET col2 = 4 WHERE id = 3;

      返回結果如下。

      777

可通過以下SQL查詢函數在特定參數類型下是否為IMMUTABLE。例如:TO_CHAR函數僅在輸入為TIMESTAMP WITH TIME ZONE類型時為IMMUTABLE,因此在產生列中使用該函數時,必須確保參數類型匹配。

SELECT n.nspname AS "Schema",
  p.proname AS "Name",
  pg_catalog.pg_get_function_result(p.oid) AS "Result data type",
  pg_catalog.pg_get_function_arguments(p.oid) AS "Argument data types",
 CASE p.prokind
  WHEN 'a' THEN 'agg'
  WHEN 'w' THEN 'window'
  WHEN 'p' THEN 'proc'
  ELSE 'func'
 END AS "Type",
 CASE
  WHEN p.provolatile = 'i' THEN 'immutable'
  WHEN p.provolatile = 's' THEN 'stable'
  WHEN p.provolatile = 'v' THEN 'volatile'
 END AS "Volatility",
 CASE
  WHEN p.proparallel = 'r' THEN 'restricted'
  WHEN p.proparallel = 's' THEN 'safe'
  WHEN p.proparallel = 'u' THEN 'unsafe'
 END AS "Parallel",
 pg_catalog.pg_get_userbyid(p.proowner) AS "Owner",
 CASE WHEN prosecdef THEN 'definer' ELSE 'invoker' END AS "Security",
 pg_catalog.array_to_string(p.proacl, E'\n') AS "Access privileges",
 l.lanname AS "Language",
 p.prosrc AS "Source code",
 pg_catalog.obj_description(p.oid, 'pg_proc') AS "Description"
FROM pg_catalog.pg_proc p
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
     LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang
-- 目標函數
WHERE p.proname OPERATOR(pg_catalog.~) '^(TO_CHAR)$' COLLATE pg_catalog.default
  AND pg_catalog.pg_function_is_visible(p.oid)
ORDER BY 1, 2, 4;