Eu tenho um banco de dados Postgresql 8.1. Em uma mesa, há três colunas: first_name
, last_name
, display_name
.
É possível definir o valor padrão de display_name
ser first_name + " " + last_name
?
Eu tenho um banco de dados Postgresql 8.1. Em uma mesa, há três colunas: first_name
, last_name
, display_name
.
É possível definir o valor padrão de display_name
ser first_name + " " + last_name
?
Respostas:
Use um gatilho.
Aqui está um código que você pode usar como base. Se você também precisar lidar com UPDATEs, apenas uma pequena alteração será necessária.
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...
com a atualização também?
Você não precisa realmente armazenar o valor; você pode criar uma função que pode ser referenciada como uma coluna gerada. A única ressalva é que as referências sempre devem ser qualificadas com o nome da tabela ou do alias.
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;
Os resultados:
id | Nome em Exibição ---- + -------------- 1 | John Smith 2 Jane Doe 3 Principe (3 linhas)
Você pode até indexar o valor gerado, incluindo o uso de pesquisas KNN com base na similaridade do trigrama. Por exemplo:
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;
Esse tipo de pesquisa retorna linhas da varredura de índice na ordem "distância" da sequência de pesquisa. Se você quiser ver o quão "próximos" eles estavam, você poderia usar o operador de distância ( <->
) ou a similarity()
função (que é 1 - distância). Uma pesquisa KNN pode retornar o K "vizinhos mais próximos" muito rapidamente, mesmo com um conjunto de dados muito grande.
last_name
estar NOT NULL
no meu exemplo. :-) Tivemos colunas de nome como as que estavam na tabela e mantidas por gatilhos e mudamos para essa abordagem sem muita dificuldade, mas nossa estrutura sempre usa um alias e sempre qualifica referências, de modo que essa parte foi fácil. Se você tiver um código que não seja consistente sobre a qualificação de referências de coluna, posso ver onde pode ser difícil rastrear todos esses casos.