¿Establecer el valor predeterminado de una columna para la concatenación de los valores de otras dos columnas?


13

Tengo una base de datos Postgresql 8.1. En una mesa, hay tres columnas: first_name, last_name, display_name.

¿Es posible establecer el valor predeterminado de display_nameser first_name + " " + last_name?


Sé que este es un post de más de 7 años. Pero, solo por curiosidad, ¿no deberías usar view para este caso? ¿No se necesitará ninguna actualización, no habrá gastos generales de almacenamiento, no se necesitará un disparador, etc.
Duro

Respuestas:


15

Usa un gatillo.

Aquí hay un código que puede usar como base. Si también necesita manejar ACTUALIZACIONES, solo se requiere un pequeño cambio.

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

¡Gracias! ¿La línea no CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...manejaría la actualización también?
MattSayar

Oh si. Debe haber estado medio dormido :)
Philᵀᴹ

display_name probablemente debería ser 41, si te importa. Como agrega un espacio entre dos columnas de 20 caracteres.
isaaclw

Veo que esta solución agrega aproximadamente un 15% de sobrecarga para la operación de inserción :-(
Akvel

17

No necesita almacenar realmente el valor; puede crear una función a la que se pueda hacer referencia de forma muy similar a una columna generada. La única advertencia es que las referencias siempre deben calificarse con la tabla o el nombre del 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;

Los resultados:

id | nombre para mostrar
---- + --------------
  1 | John Smith
  2 | fulano de tal
  3 | Príncipe
(3 filas)

Incluso puede indexar el valor generado, incluido el uso de búsquedas KNN basadas en la similitud de trigrama. Por ejemplo:

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;

Este tipo de búsqueda devuelve filas del índice de exploración en orden de "distancia" desde la cadena de búsqueda. Si desea ver cuán "cercanos" estaban, puede usar el operador de distancia ( <->) o la similarity()función (que es 1 - distancia). Una búsqueda KNN puede devolver los K "vecinos más cercanos" muy rápidamente, incluso con un conjunto de datos muy grande.


De hecho, necesito almacenar el valor para la compatibilidad con versiones anteriores, ¡pero este es un enfoque genial! La parte de OCD de mí también quiere que haya una verificación de apellidos NULOS, pero eso probablemente significaría que tiene que preocuparse por problemas de integridad de datos más grandes en ese momento
MattSayar

Bueno, declare last_nameestar NOT NULLen mi ejemplo. :-) Teníamos columnas de nombres como las que estaban en la tabla y mantenidas por disparadores y cambiamos a este enfoque sin mucho dolor, pero nuestro marco siempre usa un alias y siempre califica las referencias, por lo que esa parte fue fácil. Si tiene un código que no es coherente con las referencias de columna de calificación, puedo ver dónde podría ser difícil rastrear todos esos casos.
kgrittn

2

Con la configuración POR DEFECTO en una tabla de columnas, no.

Su mejor apuesta aquí es un GATILLO con el NUEVO valor para cada columna que desea calcular.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.