Czy ustawić domyślną wartość kolumny na łączenie wartości dwóch innych kolumn?

13

Mam bazę danych Postgresql 8.1. W jednej tabeli, istnieją trzy kolumny: first_name, last_name, display_name.

Czy można ustawić wartość domyślną display_nameto first_name + " " + last_name?

MattSayar
źródło
Wiem, że to post ma więcej niż 7 lat. Ale dla ciekawości nie powinieneś używać widoku w tej sprawie? Żadna aktualizacja nie będzie potrzebna, nie będzie narzutów w sklepie, nie będziesz potrzebować wyzwalacza itp.?
Surowy

Odpowiedzi:

15

Użyj spustu.

Oto kod, którego możesz użyć jako podstawy. Jeśli musisz także obsługiwać AKTUALIZACJE, wymagana jest tylko niewielka zmiana.

 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ᵀᴹ
źródło
Dzięki! Czy linia nie CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...poradziłaby również z aktualizacją?
MattSayar,
O tak. Musiałem być w połowie śpiący :)
Philᵀᴹ
display_name powinna prawdopodobnie mieć 41, jeśli cię to obchodzi. Ponieważ dodajesz spację między dwiema 20 kolumnami znaków.
isaaclw
Widzę, że to rozwiązanie dodaje około 15% narzutu na operację wstawiania :-(
Akvel
17

Nie musisz tak naprawdę przechowywać wartości; możesz utworzyć funkcję, do której można będzie się odwoływać podobnie do wygenerowanej kolumny. Jedynym zastrzeżeniem jest to, że odwołania muszą zawsze być kwalifikowane nazwą tabeli lub aliasu.

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;

Wyniki:

id | wyświetlana nazwa
---- + --------------
  1 | John Smith
  2 | Jane Doe
  3 | Książę
(3 rzędy)

Możesz nawet indeksować wygenerowaną wartość, w tym za pomocą wyszukiwań KNN opartych na podobieństwie trygramu. Na przykład:

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;

Ten typ wyszukiwania zwraca wiersze ze skanu indeksu w kolejności „odległości” od ciągu wyszukiwania. Jeśli chcesz zobaczyć, jak były „blisko”, możesz użyć operatora odległości ( <->) lub similarity()funkcji (która wynosi 1 - odległość). Wyszukiwanie KNN może bardzo szybko zwrócić K „najbliższych sąsiadów”, nawet przy bardzo dużym zestawie danych.

kgrittn
źródło
Właściwie muszę przechowywać wartość kompatybilności wstecznej, ale jest to całkiem fajne podejście! Część mnie z OCD chce również sprawdzić nazwiska NULL, ale to prawdopodobnie oznaczałoby, że masz większe problemy z integralnością danych, o które należy się martwić
MattSayar
Cóż, oświadczyłem last_namesię NOT NULLw moim przykładzie. :-) Mieliśmy takie kolumny nazw, które były w tabeli i były obsługiwane przez wyzwalacze i przeszły na to podejście bez większego bólu, ale nasz framework zawsze używa aliasu i zawsze kwalifikuje referencje, więc ta część była łatwa. Jeśli masz kod, który nie jest spójny w odniesieniu do kwalifikujących się odniesień do kolumn, widzę, gdzie może być problem ze śledzeniem wszystkich tych przypadków.
kgrittn
2

Z ustawieniem DOMYŚLNYM w tabeli kolumn, nie.

Twój najlepszy zakład tutaj to WYZWALACZ z NOWĄ wartością dla każdej kolumny, którą chcesz obliczyć.

rfusca
źródło