Definir o valor padrão de uma coluna para a concatenação dos valores de duas outras colunas?

13

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_nameser first_name + " " + last_name?

MattSayar
fonte
Eu sei que este é um post com mais de 7 anos. Mas, para ser curioso, você não deve usar o view neste caso? Nenhuma atualização será necessária, nenhuma sobrecarga da loja, nenhum acionador necessário etc?
Harsh

Respostas:

15

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=#
Philᵀᴹ
fonte
Obrigado! A linha não lidaria CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...com a atualização também?
MattSayar
Oh sim. Deve ter sido meio adormecido :)
Philᵀᴹ
display_name provavelmente deve ser 41, se você se importa. Como você adiciona um espaço entre duas colunas de 20 caracteres.
Isaaclw
Vejo que esta solução adiciona cerca de 15% de sobrecarga para a operação de inserção :-(
Akvel
17

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.

kgrittn
fonte
Na verdade, eu preciso armazenar o valor da compatibilidade com versões anteriores, mas essa é uma abordagem bem legal! A parte OCD de mim também quer que haja uma verificação para NULL sobrenomes, mas isso provavelmente significa que você tem maiores problemas de integridade de dados para se preocupar nesse ponto
MattSayar
Bem, eu declarei last_nameestar NOT NULLno 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.
precisa saber é o seguinte
2

Com a configuração PADRÃO em uma tabela de colunas, não.

Sua melhor aposta aqui é uma TRIGGER com o novo valor para cada coluna que você deseja calcular.

rfusca
fonte