将一列的默认值设置为其他两个列的值的串联吗?


13

我有一个Postgresql 8.1数据库。在一个表中,有三列:first_namelast_namedisplay_name

可以将默认值设置display_namefirst_name + " " + last_name吗?


我知道这是一个超过7年的职位。但是,出于好奇,您是否应该在这种情况下使用视图?不需要更新,不需要存储开销,不需要触发器等吗?
严苛的

Answers:


15

使用触发器。

这是一些您可以用作基础的代码。如果还需要处理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...处理更新吗?
MattSayar

哦耶。一定睡着了:)
菲尔(Philᵀᴹ)

如果需要的话,display_name可能应该是41。由于您在两个20个字符的列之间添加了一个空格。
isaaclw

我看到此解决方案为插入操作增加了大约15%的开销:-(
Akvel,2016年

17

您不需要实际存储值。您可以创建一个可以像生成的列一样被引用的函数。一个警告是引用必须始终使用表名或别名来限定。

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个“最近的邻居”。


实际上,我确实需要存储该值以实现向后兼容,但这是一种非常酷的方法!我的OCD部分人员也希望对NULL姓氏进行检查,但这可能意味着您那时需要担心更大的数据完整性问题
MattSayar 2012年

好吧,我宣布last_nameNOT NULL在我的例子。:-)我们在表中拥有像这样的名称列,这些名称列由触发器维护,并且切换到此方法时很轻松,但是我们的框架始终使用别名并始终限定引用,因此这一部分很容易。如果您的代码与限定列引用不一致,那么我会发现在哪里很难找到所有这些情况。
kgrittn

2

在列表上使用DEFAULT设置时,不。

最好的选择是使用要计算的每一列的NEW值的TRIGGER。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.