У меня есть база данных Postgresql 8.1. В одной таблице, есть три колонки: first_name
, last_name
, display_name
.
Можно ли установить значение по умолчанию, display_name
чтобы быть first_name + " " + last_name
?
У меня есть база данных Postgresql 8.1. В одной таблице, есть три колонки: first_name
, last_name
, display_name
.
Можно ли установить значение по умолчанию, display_name
чтобы быть first_name + " " + last_name
?
Ответы:
Используйте триггер.
Вот код, который вы можете использовать в качестве основы. Если вам также нужно обрабатывать обновления, требуется лишь небольшое изменение.
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
в моем примере. :-) У нас были столбцы имен, подобные тем, которые были в таблице и поддерживались триггерами, и без особого труда переключились на этот подход, но наша среда всегда использует псевдоним и всегда определяет ссылки, так что эта часть была легкой. Если у вас есть код, который не согласуется с квалификационными ссылками на столбцы, я могу увидеть, где может быть сложно отследить все эти случаи.