Установить значение столбца по умолчанию для объединения значений двух других столбцов?

13

У меня есть база данных Postgresql 8.1. В одной таблице, есть три колонки: first_name, last_name, display_name.

Можно ли установить значение по умолчанию, display_nameчтобы быть first_name + " " + last_name?

MattSayar
источник
Я знаю, что это более 7 лет пост. Но, просто чтобы быть любопытным, разве вы не должны использовать представление для этого случая? Нет необходимости в обновлении, нет необходимости в магазине, нет триггера и т. Д.?
Суров

Ответы:

15

Используйте триггер.

Вот код, который вы можете использовать в качестве основы. Если вам также нужно обрабатывать обновления, требуется лишь небольшое изменение.

 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=#
Philᵀᴹ
источник
Благодарность! Разве линия не CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...справится с обновлением?
MattSayar
О, да. Должно быть, я спал наполовину :)
Philᵀᴹ
display_name должно быть 41, если вам интересно. Так как вы добавляете пробел между двумя 20 столбцами символов.
Исаакль
Я вижу, что это решение добавляет около 15% накладных расходов на операцию вставки :-(
Аквел
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 «ближайших соседей», даже с очень большим набором данных.

kgrittn
источник
Мне действительно нужно хранить значение для обратной совместимости, но это довольно крутой подход! Часть моего OCD также хочет, чтобы была проверка на NULL фамилии, но это, вероятно, означало бы, что у вас есть большие проблемы с целостностью данных, о которых нужно беспокоиться в этот момент
MattSayar
Ну, я заявил, last_nameчто NOT NULLв моем примере. :-) У нас были столбцы имен, подобные тем, которые были в таблице и поддерживались триггерами, и без особого труда переключились на этот подход, но наша среда всегда использует псевдоним и всегда определяет ссылки, так что эта часть была легкой. Если у вас есть код, который не согласуется с квалификационными ссылками на столбцы, я могу увидеть, где может быть сложно отследить все эти случаи.
кгритт
2

С настройкой DEFAULT для таблицы столбцов, нет.

Ваша лучшая ставка здесь - это TRIGGER со значением NEW для каждого столбца, который вы хотите вычислить.

rfusca
источник