ตั้งค่าเริ่มต้นของคอลัมน์เป็นการต่อค่าสองคอลัมน์อื่นหรือไม่


13

ฉันมีฐานข้อมูล Postgresql 8.1 first_nameในตารางหนึ่งมีสามคอลัมน์: last_name, display_name,

มันเป็นไปได้ที่จะตั้งค่าเริ่มต้นของdisplay_nameการเป็นfirst_name + " " + last_name?


ฉันรู้ว่านี่เป็นบทความที่เก่ากว่า 7 ปี แต่เพียงแค่อยากรู้อยากเห็นคุณไม่ควรใช้มุมมองสำหรับกรณีนี้หรือไม่? ไม่จำเป็นต้องมีการอัปเดตไม่มีค่าใช้จ่ายในการจัดเก็บไม่มีทริกเกอร์ที่จำเป็น ฯลฯ
รุนแรง

คำตอบ:


15

ใช้ทริกเกอร์

นี่คือรหัสบางส่วนที่คุณสามารถใช้เป็นฐาน หากคุณต้องการจัดการกับ UPDATE ก็จำเป็นต้องทำการเปลี่ยนแปลงเล็กน้อย

 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...จัดการการอัปเดตด้วยหรือไม่
MattSayar

โอ้ใช่. คงจะครึ่งหลับ :)
Philᵀᴹ

display_name น่าจะเป็น 41 ถ้าคุณสนใจ เนื่องจากคุณเพิ่มช่องว่างระหว่างสองคอลัมน์ถ่าน 20
isaaclw

ฉันเห็นว่าโซลูชันนี้เพิ่มค่าใช้จ่ายประมาณ 15% สำหรับการดำเนินการแทรก :-(
Akvel

17

คุณไม่จำเป็นต้องเก็บค่าจริงๆ คุณสามารถสร้างฟังก์ชั่นที่สามารถอ้างอิงได้เหมือนคอลัมน์ที่สร้างขึ้น หนึ่ง caveat คือการอ้างอิงจะต้องผ่านการรับรองด้วยชื่อตารางหรือนามแฝง

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;

ผลลัพธ์ที่ได้:

id | ชื่อที่แสดง
---- + --------------
  1 | จอห์นสมิ ธ
  2 | Jane Doe
  3 | เจ้าชาย
(3 แถว)

คุณยังสามารถจัดทำดัชนีค่าที่สร้างขึ้นรวมถึงการใช้การค้นหา KNN ตามความคล้ายคลึงกันของ trigram ตัวอย่างเช่น:

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;

การค้นหาประเภทนี้ส่งคืนแถวจากการสแกนดัชนีตามลำดับ "ระยะทาง" จากสตริงการค้นหา หากคุณต้องการดูว่า "ปิด" พวกเขาเป็นอย่างไรคุณสามารถใช้ตัวดำเนินการระยะทาง ( <->) หรือsimilarity()ฟังก์ชัน (ซึ่งคือ 1 - ระยะทาง) การค้นหา KNN สามารถส่งคืน K "เพื่อนบ้านที่ใกล้ที่สุด" ได้อย่างรวดเร็วแม้จะมีชุดข้อมูลขนาดใหญ่มากก็ตาม


จริง ๆ แล้วฉันจำเป็นต้องเก็บค่าสำหรับความเข้ากันได้ย้อนหลัง แต่นี่เป็นวิธีที่ยอดเยี่ยม! ส่วน OCD ของฉันยังต้องการให้มีการตรวจสอบสำหรับ NULL นามสกุล แต่อาจจะหมายความว่าคุณมีปัญหาด้านความสมบูรณ์ของข้อมูลที่ใหญ่กว่าที่ต้องกังวลเกี่ยวกับ ณ จุดนั้น
MattSayar

ฉันประกาศว่าlast_nameจะเป็นNOT NULLตัวอย่างของฉัน :-) เรามีคอลัมน์ชื่อเหมือนที่อยู่ในตารางและบำรุงรักษาโดยทริกเกอร์และเปลี่ยนไปใช้วิธีนี้โดยไม่เจ็บปวดมาก แต่กรอบงานของเรามักใช้นามแฝงและมีคุณสมบัติอ้างอิงเสมอดังนั้นส่วนนั้นจึงเป็นเรื่องง่าย หากคุณมีรหัสที่ไม่สอดคล้องกับการอ้างอิงคอลัมน์ที่มีคุณสมบัติครบถ้วนฉันสามารถดูว่าการติดตามกรณีเหล่านั้นทั้งหมดเป็นอย่างไร
kgrittn

2

ด้วยการตั้งค่าเริ่มต้นบนตารางคอลัมน์ไม่

ทางออกที่ดีที่สุดของคุณที่นี่คือ TRIGGER ที่มีค่าใหม่สำหรับแต่ละคอลัมน์ที่คุณต้องการคำนวณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.