Встановити значення за замовчуванням стовпця на об'єднання значень двох інших стовпців?


13

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

Чи можна встановити значення за замовчуванням, display_nameяке буде first_name + " " + last_name?


Я знаю, що це посада більше 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=#

Спасибі! Чи не CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...оброблятиметься також оновлення?
MattSayar

О так. Мабуть, заснув :)
Philᵀᴹ

Якщо ви байдуже, display_name, мабуть, має бути 41. Оскільки ви додали пробіл між двома 20-ти стовпчиками.
isaaclw

Я бачу, що це рішення додає приблизно 15% накладних витрат на роботу з вставкою :-(
Akvel

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 | display_name
---- + --------------
  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

Що ж, я декларував last_nameце NOT NULLна своєму прикладі. :-) У нас були такі стовпці з іменами, які були в таблиці та підтримуються тригерами, і без особливого болю переходили на цей підхід, але наша рамка завжди використовує псевдонім і завжди кваліфікує посилання, так що ця частина була легкою. Якщо у вас є код, який не відповідає класифікованим посиланням на стовпці, я можу побачити, де можна було б відшукати всі ці випадки.
kgrittn

2

Налаштування DEFAULT на таблиці стовпців, ні.

Ваша найкраща ставка тут - TRIGGER зі значенням NEW для кожного розрахованого стовпця.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.