PostgreSQL: คอลัมน์ที่สร้าง


16

PostgreSQL สนับสนุนคอลัมน์ที่สร้างขึ้นหรือไม่ ก็รู้ว่าเป็นคอลัมน์เสมือน ฉันกำลังไม่ได้พูดคุยเกี่ยวกับคอลัมน์IDENTITY

ฉันไม่สามารถหาข้อมูลเกี่ยวกับคุณสมบัติที่น่าทึ่งนี้ได้ แต่ฉันรู้ว่ามันมีอยู่ใน SQL Server และใน MariaDB & MySQL เวอร์ชันล่าสุด

คุณลักษณะดังกล่าวได้รับการกล่าวถึงในมาตรฐานSQL: 2003และมีการพูดคุยกันในฟอรัม PostgreSQL ประมาณปี 2549 แต่ฉันไม่พบสิ่งใดในเนื้อหา

มีการอภิปรายเกี่ยวกับ SO แต่ตอนนี้ค่อนข้างเก่าแล้วดังนั้นจึงอาจล้าสมัย


2
คำตอบที่เกี่ยวข้องจากปี 2012 บน SO อาจช่วยได้: stackoverflow.com/questions/11165450/…ยังใช้ได้
Erwin Brandstetter

@ErwinBrandstetter ขออภัยฉันพลาดความเห็นนี้ไปแล้ว มันเป็นเคล็ดลับที่มีประโยชน์ ขอบคุณ
Manngo

คำตอบ:


17

ไม่แน่ใจว่านี่คือสิ่งที่คุณต้องการหรือไม่ แต่สัญกรณ์คุณลักษณะrow.full_nameและสัญกรณ์ฟังก์ชั่นfull_name(row)เทียบเท่าใน postgresql

นั่นหมายถึงคุณนั่งโต๊ะ

CREATE TABLE people (
  first_name text,
  last_name text
);

และฟังก์ชั่น:

CREATE FUNCTION full_name(people) RETURNS text AS $$
  SELECT $1.first_name || ' ' || $1.last_name;
$$ LANGUAGE SQL;

และเรียกมันว่าสิ่งนี้:

select full_name from people

นั่นคือสิ่งที่คุณต้องการ?

เพื่อเพิ่มความเร็วในสิ่งต่าง ๆ คุณสามารถสร้างดัชนีนิพจน์:

CREATE INDEX people_full_name_idx ON people
USING GIN (to_tsvector('english', full_name(people)));

หรือเก็บทุกอย่างไว้ในมุมมองที่ปรากฏ

ตัวอย่างที่นำมาจากที่นี่: http://bernardoamc.github.io/sql/2015/05/11/postgres-virtual-columns/


2
นี่คือคำตอบที่ถูกต้อง ดูตัวอย่างว่าPostgrestอ้างถึงพฤติกรรมนี้อย่างไรในฐานะ "คอลัมน์ที่คำนวณ"
fiatjaf

สะกดผิดผมคิดว่า - เลือกควรจะเป็นselect people.full_name from peopleหรือselect full_name(people) from people?
Barguast

ไม่ทำงานอย่างนั้น คำนำหน้าใน "select people.full_name จากคน" สามารถนำออกมาเหมือนใน SQL ปกติ
Fabian Zeindl

ฉันพลาดคำตอบนี้มาเหมือนเดิมนานหลังจากที่ฉันยอมแพ้ ขอบคุณสำหรับคำแนะนำ
Manngo

1
คุณเปลี่ยนคำตอบที่ยอมรับแล้วได้ไหม?
Fabian Zeindl

6

ไม่ปัจจุบันยังไม่รองรับ (ตั้งแต่ Postgres 9.6)

วิธีแก้ปัญหาเพียงอย่างเดียวคือใช้ทริกเกอร์หรือมุมมองหากเป็นการคำนวณแบบง่ายที่คุณไม่จำเป็นต้องทำดัชนี


หนู ฉันคิดว่าฉันสามารถไปดู materialized ถ้าฉันต้องการประสิทธิภาพ ฉันได้เพิ่มคำขอคุณลักษณะดังกล่าวเนื่องจากมีให้บริการแล้วในการแข่งขัน
Manngo

1
ไม่จำเป็นต้องมี MVIEW คอลัมน์ที่มีทริกเกอร์จะช่วยให้คุณสามารถจัดทำดัชนีเนื้อหาของคอลัมน์
a_horse_with_no_name

ฉันมีปัญหาเกี่ยวกับปรัชญากับการจัดเก็บคอลัมน์จริงเพิ่มเติมซึ่งโดยทั่วไปแล้วเป็นการทำซ้ำของข้อมูลอื่น มันยกเลิกตารางปกติ
Manngo

5
คอลัมน์ที่คำนวณได้คือ: การจัดเก็บข้อมูลที่ถูกทำให้เป็นมาตรฐาน วิธีการสร้างค่าของคอลัมน์ที่คำนวณนั้นไม่สำคัญ ฉันไม่เห็นความแตกต่างทางแนวคิดระหว่างคอลัมน์ที่คำนวณ "ของจริง" กับคอลัมน์ที่สร้างขึ้นจากทริกเกอร์
a_horse_with_no_name

วิธีแก้ปัญหาอื่น (สำหรับบางกรณี) คือการจัดทำดัชนีนิพจน์
ypercubeᵀᴹ

5

ใช่: GENERATED ALWAYS AS … STORED

Postgres 12เพิ่มฟังก์ชันการทำงานสำหรับคอลัมน์ที่สร้างขึ้นเป็นที่กล่าวถึงในSQL: 2003 ที่มาตรฐาน

ค่าจะถูกสร้างขึ้นในช่วงเวลาของINSERTหรือUPDATEจากนั้นเก็บไว้กับแถวเช่นค่าอื่น ๆ

ที่สร้างขึ้นจะต้องอยู่บนพื้นฐานของคอลัมน์ฐานของตารางเดียวกันหรือในฟังก์ชั่นที่ไม่เปลี่ยนรูป

ไวยากรณ์ง่ายประโยคบนCREATE TABLE:

GENERATED ALWAYS AS ( generation_expr ) STORED 

ตัวอย่าง:

CREATE TABLE people (
    ...,
    height_cm NUMERIC,
    height_in NUMERIC GENERATED ALWAYS AS ( height_cm / 2.54 ) STORED
);

คุณสมบัติ:

  • สามารถจัดทำดัชนี
  • ส่วนหนึ่งของมาตรฐาน SQL

คำเตือน:

  • ตามคอลัมน์ของตารางเดียวกัน (ไม่ใช่ตารางที่เกี่ยวข้อง)
  • ไม่อนุญาตให้แบ่งพาร์ติชัน (ไม่สามารถเป็นส่วนหนึ่งของคีย์พาร์ติชัน)
  • ข้อมูลถูกเขียนลงในแถวเสมอทำให้มีพื้นที่ในการจัดเก็บ
    • คุณลักษณะในอนาคตอาจเสนอ VIRTUAL สำหรับค่าที่คำนวณได้แบบทันทีโดยไม่มีที่เก็บข้อมูล
  • Single-generation deep (ใช้คอลัมน์ฐานไม่ใช่คอลัมน์อื่นที่สร้างขึ้น)
  • ไม่มีการสร้างโดยค่าเริ่มต้น (คุณไม่สามารถแทนที่ค่า)
  • ไม่สามารถเข้าถึง gen-col ในทริกเกอร์ก่อน (ยังไม่ได้กำหนดค่า)
  • ฟังก์ชั่นจะต้องไม่เปลี่ยนรูป

ดู:


ขอบคุณสำหรับข้อมูลนั้น ฉันเห็นว่าเวอร์ชั่น 12 ยังไม่วางจำหน่าย แต่ฉันหวังว่าจะเป็นเช่นนั้น ฉันทราบว่า PostgreSQL ใช้ไวยากรณ์มาตรฐานมากกว่า แต่อย่างอื่นเหมือนกับ MSSQL ผมพบว่าข้อกำหนด SQL2003 ที่นี่: sigmodrecord.org/publications/sigmodRecord/0403/... ฉันได้กล่าวเสมอว่า SQL เป็นมาตรฐานที่เคลื่อนไหวช้ามากและการใช้งาน DBMS นั้นช้ามาก
Manngo

0

ขึ้นอยู่กับกรณีการใช้งานของคุณคุณสามารถบรรลุพฤติกรรมประเภทนี้โดยการประกาศคอลัมน์ใหม่และเติมด้วยทริกเกอร์ในการแทรก / ปรับปรุง

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

ฉันพิจารณาวิธีการนี้เพื่อจัดการกับปัญหาที่บางครั้งฉันมีเพียง 15 หลักของรหัส 18 หลัก (3 หลักสุดท้ายเป็นเพียงการตรวจสอบ) แต่ต้องการที่จะสามารถบังคับใช้ความสัมพันธ์กับคีย์ต่างประเทศได้

PG เอกสารเกี่ยวกับทริกเกอร์: https://www.postgresql.org/docs/9.6/sql-createtrigger.html

ตัวอย่าง W3: https://www.w3resource.com/PostgreSQL/postgresql-triggers.php

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