簡體   English   中英

為什么在 PostgreSQL 中創建生成的列時出現錯誤?

[英]Why am I getting a an error when creating a generated column in PostgreSQL?

CREATE TABLE my_app.person
(
    person_id smallserial NOT NULL,
    first_name character varying(50),
    last_name character varying(50),
    full_name character varying(100) generated always as (concat(first_name, ' ', last_name)) STORED,
    birth_date date,
    created_timestamp timestamp default current_timestamp,
    PRIMARY KEY (person_id)
);

錯誤:生成表達式不是一成不變的

目標是將名字和姓氏填充到全名列中。

concat()不是IMMUTABLE (僅STABLE ),因為它可以調用依賴於語言環境設置的數據類型輸出函數(如timestamptz_out )。 Tom Lane(核心開發人員)在這里解釋了它。

first_name || ' ' || last_name first_name || ' ' || last_name first_name || ' ' || last_name等同於concat(first_name, ' ', last_name)而至少一列可以是NULL

詳細解釋:

解決方案

要使其工作,完全按照您演示的方式:

CREATE TABLE person (
  person_id smallserial PRIMARY KEY
, first_name varchar(50)
, last_name  varchar(50)
, full_name  varchar(101) GENERATED ALWAYS AS
                         (CASE WHEN first_name IS NULL THEN last_name
                               WHEN last_name  IS NULL THEN first_name
                               ELSE first_name || ' ' || last_name END) STORED
, ...
);

db<> 在這里擺弄

CASE表達式盡可能快 - 比多個串聯和函數調用快得多。 並且完全正確。

或者如果您知道自己在做什么並擁有必要的權限,請創建一個IMMUTABLE concat 函數,如下所示(替換CASE表達式):

旁白: full_name需要是varchar(101) (50+50+1) 才有意義。 或者只是使用text列。 看:

一般建議

最佳解決方案取決於您計划如何准確處理 NULL 值(和空字符串)。 我可能不會添加生成的列,這通常比即時連接全名更昂貴且更容易出錯。 考慮一個視圖。 或者封裝精確連接邏輯的函數。

有關的:

這適用於|| 操作員:

CREATE TABLE person (
    person_id smallserial NOT NULL,
    first_name character varying(50),
    last_name character varying(50),
    full_name character varying(100) generated always as (first_name || ' ' || last_name) STORED,
    birth_date date,
    created_timestamp timestamp default current_timestamp,
    PRIMARY KEY (person_id)
);

我不確定concat()被認為是可變的技術原因,但是|| 不是。

如果要處理列中的NULL值,則稍微復雜一些。 我可能會推薦:

trim(both ' ' from
     (' ' || coalesce(first_name, '') || ' ' || coalesce(last_name, '')
     )
    )

當然,這與您的表達式不完全相同,因為它從名稱的開頭和結尾刪除了空格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM