Définir la valeur par défaut d'une colonne sur la concaténation des valeurs de deux autres colonnes?

13

J'ai une base de données Postgresql 8.1. Dans une table, il y a trois colonnes: first_name, last_name, display_name.

Est-il possible de définir la valeur par défaut de display_nameêtre first_name + " " + last_name?

MattSayar
la source
Je sais que c'est un poste de plus de 7 ans. Mais, juste pour être curieux, ne devriez-vous pas utiliser la vue pour ce cas? Aucune mise à jour ne sera nécessaire, aucune surcharge de magasin, aucun déclencheur nécessaire, etc.?
Harsh

Réponses:

15

Utilisez un déclencheur.

Voici du code que vous pouvez utiliser comme base. Si vous devez également gérer les MISES À JOUR, seule une petite modification est requise.

 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ᵀᴹ
la source
Merci! La ligne ne gérerait-elle pas également la CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...mise à jour?
MattSayar
Oh oui. Doit être à moitié endormi :)
Philᵀᴹ
display_name devrait probablement être 41, si vous vous en souciez. Puisque vous ajoutez un espace entre deux colonnes de 20 caractères.
isaaclw
Je vois que cette solution ajoute environ 15% de frais généraux pour l'opération d'insertion :-(
Akvel
17

Vous n'avez pas besoin de stocker réellement la valeur; vous pouvez créer une fonction qui peut être référencée un peu comme une colonne générée. La seule mise en garde est que les références doivent toujours être qualifiées avec le nom de la table ou de l'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;

Les resultats:

id | Afficher un nom
---- + --------------
  1 | John Smith
  2 | Jane Doe
  3 | Prince
(3 rangées)

Vous pouvez même indexer la valeur générée, notamment en utilisant des recherches KNN basées sur la similitude des trigrammes. Par exemple:

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;

Ce type de recherche renvoie les lignes de l'analyse d'index par ordre de "distance" par rapport à la chaîne de recherche. Si vous voulez voir à quel point ils étaient "proches", vous pouvez utiliser l'opérateur de distance ( <->) ou la similarity()fonction (qui est 1 - distance). Une recherche KNN peut renvoyer les K "voisins les plus proches" très rapidement, même avec un ensemble de données très volumineux.

kgrittn
la source
En fait, j'ai besoin de stocker la valeur pour la compatibilité descendante, mais c'est une approche assez cool! La partie OCD de moi veut également qu'il y ait une vérification des noms de famille NULL, mais cela signifierait probablement que vous avez de plus gros problèmes d'intégrité des données à vous inquiéter à ce moment
MattSayar
Eh bien, j'ai déclaré last_nameêtre NOT NULLdans mon exemple. :-) Nous avions des colonnes de noms comme celle qui étaient dans le tableau et maintenues par des déclencheurs et nous sommes passés à cette approche sans trop de peine, mais notre framework utilise toujours un alias et qualifie toujours les références, donc cette partie était facile. Si vous avez du code qui n'est pas cohérent avec les références de colonne qualifiées, je peux voir où cela pourrait être difficile de retrouver tous ces cas.
kgrittn
2

Avec le paramètre DEFAULT sur une table de colonnes, non.

Votre meilleur pari ici est un TRIGGER avec la NOUVELLE valeur pour chaque colonne que vous souhaitez calculer.

rfusca
la source