產生列(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時
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。
使用樣本
建立帶有產生列的表。
CREATE TABLE generated_col_t ( id INT PRIMARY KEY, col1 INT, col2 INT GENERATED ALWAYS AS (col1 + 1) STORED );資料匯入。
支援資料匯入全部非產生列。樣本如下:
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);返回結果如下。

資料更新。
支援更新非產生列資料。樣本如下:
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;返回結果如下。

可通過以下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;