Impostare il valore predefinito di una colonna sulla concatenazione dei valori di altre due colonne?


13

Ho un database Postgresql 8.1. In una tabella, ci sono tre colonne: first_name, last_name, display_name.

È possibile impostare il valore predefinito di display_nameessere first_name + " " + last_name?


So che questo è un post di oltre 7 anni. Ma, solo per essere curiosi, non dovresti usare view per questo caso? Non sarà necessario alcun aggiornamento, nessun overhead dello store, nessun trigger necessario ecc.?
Duro

Risposte:


15

Usa un grilletto.

Ecco un po 'di codice che puoi usare come base. Se è necessario gestire anche gli AGGIORNAMENTI, è necessaria solo una piccola modifica.

 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=#

Grazie! La linea non CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...gestirà anche l'aggiornamento?
MattSayar,

O si. Deve essere stato mezzo addormentato :)
Phil

display_name dovrebbe probabilmente essere 41, se ti interessa. Dato che aggiungi uno spazio tra due colonne da 20 caratteri.
Isaaclw,

Vedo che questa soluzione aggiunge circa il 15% di sovraccarico per l'operazione di inserimento :-(
Akvel

17

Non è necessario archiviare effettivamente il valore; puoi creare una funzione a cui puoi fare riferimento in modo molto simile a una colonna generata. L'unica avvertenza è che i riferimenti devono sempre essere qualificati con il nome della tabella o 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;

I risultati:

id | nome da visualizzare
---- + --------------
  1 | John Smith
  2 | Jane Doe
  3 | Principe
(3 file)

Puoi persino indicizzare il valore generato, incluso l'uso delle ricerche KNN basate sulla somiglianza del trigramma. Per esempio:

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;

Questo tipo di ricerca restituisce le righe dalla scansione dell'indice in ordine di "distanza" dalla stringa di ricerca. Se vuoi vedere quanto fossero "vicini", puoi usare l'operatore di distanza ( <->) o la similarity()funzione (che è 1 - distanza). Una ricerca KNN può restituire K "vicini più vicini" molto rapidamente, anche con un set di dati molto grande.


In realtà ho bisogno di memorizzare il valore per la retrocompatibilità, ma questo è un approccio piuttosto interessante! La parte OCD di me vuole anche che ci sia un controllo per i cognomi NULL, ma ciò significherebbe probabilmente che hai problemi di integrità dei dati più grandi di cui preoccuparti a quel punto
MattSayar

Bene, ho dichiarato last_namedi essere NOT NULLnel mio esempio. :-) Avevamo nomi di colonne come quelli che erano nella tabella e mantenuti dai trigger e passati a questo approccio senza troppi problemi, ma il nostro framework utilizza sempre un alias e qualifica sempre i riferimenti, quindi quella parte è stata facile. Se hai un codice che non è coerente con i riferimenti alle colonne qualificanti, posso vedere dove potrebbe essere difficile rintracciare tutti quei casi.
kgrittn,

2

Con l'impostazione DEFAULT su una tabella di colonne, no.

La tua scommessa migliore qui è un TRIGGER con il NUOVO valore per ogni colonna che vuoi calcolare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.