Answers:
使用触发器。
这是一些您可以用作基础的代码。如果还需要处理UPDATE,则只需要进行很小的更改。
create table people
(
first_name varchar(20),
last_name varchar(20),
display_name varchar(40)
);
CREATE TABLE
CREATE OR REPLACE FUNCTION people_insert() RETURNS trigger AS '
BEGIN
NEW.display_name := NEW.first_name||'' ''||NEW.last_name;
RETURN NEW;
END;
' LANGUAGE plpgsql;
postgres=# CREATE FUNCTION
CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE ON people FOR
EACH ROW EXECUTE PROCEDURE people_insert();
postgres=# CREATE TRIGGER
insert into people values ('Larry','Ellison');
postgres=# INSERT 0 1
postgres=# select * from people;
first_name | last_name | display_name
------------+-----------+---------------
Larry | Ellison | Larry Ellison
(1 row)
postgres=#
CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...
处理更新吗?
您不需要实际存储值。您可以创建一个可以像生成的列一样被引用的函数。一个警告是引用必须始终使用表名或别名来限定。
CREATE TABLE person
(
id int PRIMARY KEY,
first_name text,
last_name text NOT NULL
);
INSERT INTO person
VALUES
(1, 'John', 'Smith'),
(2, 'Jane', 'Doe'),
(3, NULL, 'Prince');
CREATE FUNCTION display_name(rec person)
RETURNS text
STABLE
LANGUAGE SQL
COST 5
AS $$
SELECT
CASE
WHEN $1.first_name IS NULL THEN ''
ELSE $1.first_name || ' '
END || $1.last_name;
$$;
SELECT p.id, p.display_name FROM person p;
结果:
id | 显示名称 ---- + -------------- 1 | 约翰·史密斯 2 | 简·多伊 3 | 王子 (3列)
您甚至可以索引生成的值,包括使用基于三字组相似度的KNN搜索。例如:
CREATE EXTENSION pg_trgm;
CREATE INDEX person_trgm_name
ON person
USING gist
(display_name(person) gist_trgm_ops);
SELECT
p.id,
p.display_name,
similarity(p.display_name, 'Jane')
FROM person p
ORDER BY p.display_name <-> 'Jane'
LIMIT 2;
这种类型的搜索以与搜索字符串“距离”的顺序返回索引扫描的行。如果要查看它们有多“闭合”,可以使用距离运算符(<->
)或similarity()
函数(即1-距离)。即使具有非常大的数据集,KNN搜索也可以非常快速地返回K个“最近的邻居”。
last_name
要NOT NULL
在我的例子。:-)我们在表中拥有像这样的名称列,这些名称列由触发器维护,并且切换到此方法时很轻松,但是我们的框架始终使用别名并始终限定引用,因此这一部分很容易。如果您的代码与限定列引用不一致,那么我会发现在哪里很难找到所有这些情况。