Bir sütunun varsayılan değerini diğer iki sütunun değerlerinin birleşimine mi ayarladınız?


13

Postgresql 8.1 veritabanım var. Bir tabloda, üç sütun vardır: first_name, last_name, display_name.

O varsayılan değerini ayarlamak mümkün mü display_nameolmak first_name + " " + last_name?


Bunun 7 yıldan daha eski bir yazı olduğunu biliyorum. Ancak, sadece merak etmek için, bu vaka için görünümü kullanmamalısınız? Güncelleme gerekmeyecek, mağaza yükü yok, tetikleyici gerekmiyor vb.?
sert

Yanıtlar:


15

Bir tetikleyici kullanın.

Temel olarak kullanabileceğiniz bazı kodlar. UPDATE'leri de ele almanız gerekiyorsa, yalnızca küçük bir değişiklik yapmanız gerekir.

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

Teşekkürler! Hat CREATE TRIGGER people_insert BEFORE INSERT OR UPDATE...güncellemeyi de ele almaz mı?
MattSayar

Ah evet. Yarı uyuyor
olmalıyım

Eğer önemsiyorsanız display_name muhtemelen 41 olmalıdır. İki 20 karakterlik sütun arasına boşluk eklediğiniz için.
isaaclw

Bu çözümün kesici uç işlemi için yaklaşık% 15 ek yük
getirdiğini görüyorum

17

Aslında değeri saklamanız gerekmez ; oluşturulan bir sütuna çok benzeyen bir işlev oluşturabilirsiniz. Bir uyarı, referansların her zaman tablo veya takma adla nitelendirilmesi gerektiğidir.

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;

Sonuçlar:

id | ekran adı
---- + --------------
  1 | John Smith
  2 | Jane Doe
  3 | prens
(3 sıra)

Trigram benzerliğine dayalı KNN aramalarını kullanmak da dahil olmak üzere, oluşturulan değer üzerinde dizin oluşturabilirsiniz. Örneğin:

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;

Bu tür bir arama, arama dizesinden "mesafe" sırasıyla dizin taramasından satırları döndürür. Ne kadar "yakın" olduklarını görmek isterseniz, uzaklık operatörünü ( <->) veya similarity()işlevi (1 - mesafe) kullanabilirsiniz. Bir KNN araması, K "en yakın komşularını" çok büyük bir veri kümesinde bile çok hızlı bir şekilde döndürebilir.


Aslında geriye dönük uyumluluk için değeri saklamam gerekiyor, ama bu oldukça havalı bir yaklaşım! OKB kısmı da NULL soyadları için bir kontrol olmasını istiyor, ancak bu muhtemelen endişelenecek daha büyük veri bütünlüğü sorunlarınız olduğu anlamına gelir
MattSayar

Eh, ilan last_nameolmaya NOT NULLbenim örnekte. :-) Tabloda bulunan ve tetikleyiciler tarafından korunan ve çok fazla acı çekmeden bu yaklaşıma geçiş yapan isim sütunlarımız vardı, ancak çerçevemiz her zaman bir takma ad kullanıyor ve referansları nitelendiriyor, bu yüzden bu kısım kolaydı. Nitelikli sütun referansları hakkında tutarlı olmayan bir kodunuz varsa, tüm bu durumları izlemenin bir acı olabileceğini görebiliyorum.
kgrittn

2

Sütun tablosundaki VARSAYILAN ayarı ile hayır.

Buradaki en iyi bahis, hesaplanmasını istediğiniz her sütun için YENİ değerine sahip bir TRIGGER'dir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.