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_name
ser first_name + " " + last_name
?
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_name
ser first_name + " " + last_name
?
Respuestas:
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=#
CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...
manejaría la actualización también?
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.
last_name
estar NOT NULL
en 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.