Den Standardwert einer Spalte auf die Verkettung der Werte von zwei anderen Spalten festlegen?

13

Ich habe eine Postgresql 8.1-Datenbank. In einer Tabelle gibt es drei Spalten: first_name, last_name, display_name.

Ist es möglich, den Standardwert von display_namezu setzen first_name + " " + last_name?

MattSayar
quelle
Ich weiß, dass dies ein mehr als 7 Jahre alter Beitrag ist. Aber um neugierig zu sein, sollten Sie die Ansicht nicht für diesen Fall verwenden? Es wird kein Update benötigt, kein Speicheraufwand, kein Auslöser usw.?
Harte

Antworten:

15

Verwenden Sie einen Abzug.

Hier ist ein Code, den Sie als Basis verwenden können. Wenn Sie auch UPDATEs verarbeiten müssen, ist nur eine kleine Änderung erforderlich.

 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ᵀᴹ
quelle
Vielen Dank! Wäre die Leitung nicht auch für CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...die Aktualisierung zuständig?
MattSayar
Oh ja.
Muss
display_name sollte wahrscheinlich 41 sein, wenn es dich interessiert. Da Sie ein Leerzeichen zwischen zwei 20 Zeichen Spalten hinzufügen.
Isaaclw
Ich sehe, dass diese Lösung etwa 15% Overhead für die Einfügeoperation hinzufügt :-(
Akvel
17

Sie müssen den Wert nicht wirklich speichern . Sie können eine Funktion erstellen, auf die ähnlich wie auf eine generierte Spalte verwiesen werden kann. Die einzige Einschränkung ist, dass Referenzen immer mit dem Tabellen- oder Aliasnamen qualifiziert werden müssen.

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;

Die Ergebnisse:

id | Anzeigename
---- + --------------
  1 | John Smith
  2 | Jane Doe
  3 | Prinz
(3 Reihen)

Sie können den generierten Wert sogar indizieren, einschließlich der Verwendung von KNN-Suchen basierend auf der Trigrammähnlichkeit. Beispielsweise:

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;

Diese Art der Suche gibt Zeilen aus dem Index-Scan in der Reihenfolge der "Entfernung" von der Suchzeichenfolge zurück. Wenn Sie sehen möchten, wie "nah" sie waren, können Sie entweder den Entfernungsoperator ( <->) oder die similarity()Funktion (dh 1 - Entfernung) verwenden. Eine KNN-Suche kann sehr schnell die K "nächsten Nachbarn" zurückgeben, selbst bei einem sehr großen Datensatz.

kgrittn
quelle
Eigentlich muss ich den Wert aus Gründen der Abwärtskompatibilität speichern, aber das ist ein ziemlich cooler Ansatz! Der OCD-Teil von mir möchte auch, dass auf NULL-Nachnamen geprüft wird, aber das würde wahrscheinlich bedeuten, dass Sie zu diesem Zeitpunkt größere Probleme mit der Datenintegrität haben
MattSayar,
Nun, ich erklärte last_name, NOT NULLin meinem Beispiel zu sein. :-) Wir hatten Namensspalten wie die, die in der Tabelle waren und von Triggern gepflegt und ohne großen Aufwand auf diesen Ansatz umgestellt wurden, aber unser Framework verwendet immer einen Alias ​​und qualifiziert immer Referenzen, sodass dieser Teil einfach war. Wenn Sie Code haben, der hinsichtlich der Qualifizierung von Spaltenreferenzen nicht konsistent ist, kann ich sehen, wo es ein Problem sein kann, all diese Fälle aufzuspüren.
Freitag,
2

Mit der DEFAULT-Einstellung für eine Spaltentabelle, nein.

Ihre beste Wette ist hier ein TRIGGER mit dem NEUEN Wert für jede Spalte, die Sie berechnen möchten.

rfusca
quelle