Tetapkan nilai default kolom ke gabungan nilai dua kolom lainnya?

13

Saya memiliki database Postgresql 8.1. Dalam satu meja, ada tiga kolom: first_name, last_name, display_name.

Apakah mungkin untuk menetapkan nilai default display_namemenjadi first_name + " " + last_name?

MattSayar
sumber
Saya tahu ini adalah pos yang lebih dari 7 tahun. Tapi, hanya ingin tahu, bukankah Anda harus menggunakan tampilan untuk kasus ini? Tidak ada pembaruan yang diperlukan, tidak ada overhead toko, tidak ada pemicu diperlukan dll?
Harsh

Jawaban:

15

Gunakan pemicu.

Berikut beberapa kode yang dapat Anda gunakan sebagai basis. Jika Anda juga perlu menangani UPDATE, hanya perubahan kecil diperlukan.

 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ᵀᴹ
sumber
Terima kasih! Bukankah garis juga CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...menangani pembaruan?
MattSayar
Oh ya. Pasti setengah tertidur :)
Philᵀᴹ
display_name mungkin harus 41, jika Anda peduli. Karena Anda menambahkan spasi antara dua kolom 20 karakter.
isaaclw
Saya melihat bahwa solusi ini menambahkan sekitar 15% overhead untuk operasi insert :-(
Akvel
17

Anda tidak perlu benar-benar menyimpan nilai; Anda dapat membuat fungsi yang dapat dirujuk seperti kolom yang dibuat. Satu peringatan adalah bahwa referensi harus selalu memenuhi syarat dengan tabel atau nama 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;

Hasil:

id | nama tampilan
---- + --------------
  1 | John Smith
  2 | Jane Doe
  3 | Pangeran
(3 baris)

Anda bahkan dapat mengindeks nilai yang dihasilkan, termasuk menggunakan pencarian KNN berdasarkan kesamaan trigram. Sebagai contoh:

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;

Jenis pencarian ini mengembalikan baris dari pemindaian indeks dengan urutan "jarak" dari string pencarian. Jika Anda ingin melihat seberapa "dekat" mereka, Anda bisa menggunakan operator jarak ( <->) atau similarity()fungsinya (yaitu 1 - jarak). Pencarian KNN dapat mengembalikan K "tetangga terdekat" dengan sangat cepat, bahkan dengan kumpulan data yang sangat besar.

kgrittn
sumber
Saya sebenarnya perlu menyimpan nilai untuk kompatibilitas ke belakang, tetapi ini adalah pendekatan yang cukup keren! Bagian OCD dari saya juga ingin ada pemeriksaan untuk nama belakang NULL, tapi itu mungkin berarti Anda memiliki masalah integritas data yang lebih besar untuk dikhawatirkan pada saat itu
MattSayar
Baiklah, saya menyatakan last_namesebagai NOT NULLcontoh saya. :-) Kami memiliki kolom nama seperti itu yang ada di tabel dan dikelola oleh pemicu dan beralih ke pendekatan ini tanpa banyak kesulitan, tetapi kerangka kerja kami selalu menggunakan alias dan selalu memenuhi syarat referensi, sehingga bagian itu mudah. Jika Anda memiliki kode yang tidak konsisten tentang referensi kolom yang memenuhi syarat, saya bisa melihat di mana sulitnya melacak semua kasus tersebut.
kgrittn
2

Dengan pengaturan DEFAULT pada tabel kolom, tidak.

Taruhan terbaik Anda di sini adalah TRIGGER dengan nilai BARU untuk setiap kolom yang ingin Anda hitung.

rfusca
sumber