PostgreSQL: Kolom yang Dihasilkan

16

Apakah PostgreSQL mendukung kolom yang dihasilkan ? Juga dikenal sebagai kolom virtual . Saya tidak berbicara tentang IDENTITYkolom .

Saya tidak dapat menemukan informasi tentang fitur luar biasa ini tetapi saya tahu bahwa itu tersedia di SQL Server, dan dalam versi terbaru dari MariaDB & MySQL.

Fitur ini disebutkan dalam standar SQL: 2003 , dan ada beberapa diskusi di forum PostgreSQL sekitar tahun 2006, tetapi saya tidak dapat menemukan sesuatu yang substansial mengenai masalah ini.

Ada beberapa diskusi tentang SO, tetapi sekarang sudah cukup lama, jadi mungkin sudah ketinggalan zaman.

Manngo
sumber
2
Jawaban terkait ini dari 2012 pada SO mungkin dapat membantu: stackoverflow.com/questions/11165450/… Masih valid.
Erwin Brandstetter
@ErwinBrandstetter Maaf saya melewatkan komentar ini. Ini trik yang berguna. Terima kasih.
Manngo

Jawaban:

17

Tidak yakin apakah ini yang Anda inginkan, tetapi notasi atribut row.full_namedan notasi fungsi full_name(row)setara dalam postgresql.

Itu berarti Anda mengambil meja

CREATE TABLE people (
  first_name text,
  last_name text
);

dan fungsi:

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

dan menyebutnya seperti ini:

select full_name from people

Apakah itu yang kamu butuhkan?

Untuk mempercepat Anda dapat membuat indeks ekspresi:

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

Atau simpan segala sesuatu dalam tampilan terwujud.

Contoh diambil dari sini: http://bernardoamc.github.io/sql/2015/05/11/postgres-virtual-columns/

Fabian Zeindl
sumber
2
Ini jawaban yang benar. Lihat, misalnya, bagaimana Postgrest menyebut perilaku ini sebagai "kolom yang dikomputasi".
fiatjaf
Typo, saya pikir - pilih harus dari select people.full_name from peopleatau select full_name(people) from people?
Barguast
Tidak, itu berfungsi seperti itu. Awalan di "select people.full_name from people" dapat ditinggalkan seperti dalam SQL biasa.
Fabian Zeindl
Saya melewatkan jawaban ini, datang, seolah-olah, lama setelah saya menyerah. Terima kasih untuk sarannya.
Manngo
1
Bisakah Anda mengubah jawaban yang diterima?
Fabian Zeindl
6

Tidak, ini saat ini (pada Postgres 9.6) tidak didukung.

Satu-satunya solusi adalah dengan menggunakan pemicu atau tampilan jika ini adalah perhitungan sederhana yang tidak perlu Anda indeks.

seekor kuda tanpa nama
sumber
Tikus Saya kira saya bisa pergi untuk tampilan terwujud jika saya membutuhkan kinerja. Saya telah menambahkan permintaan untuk fitur ini, karena sudah tersedia di kompetisi.
Manngo
1
Tidak perlu untuk MVIEW. Kolom dengan pemicu juga akan memungkinkan Anda mengindeks konten kolom
a_horse_with_no_name
Saya memiliki masalah filosofis dengan menyimpan kolom nyata tambahan yang pada dasarnya merupakan pengulangan dari data lainnya. Ini menonaktifkan tabel.
Manngo
5
Ya, kolom yang dikomputasi persis seperti itu: menyimpan data yang tidak dinormalisasi. Bagaimana nilai kolom yang dihitung dihasilkan tidak masalah. Saya tidak melihat perbedaan konseptual antara kolom yang dihitung "nyata" dan yang dihasilkan melalui pemicu
a_horse_with_no_name
Solusi lain (untuk beberapa kasus) adalah mengindeks ekspresi.
ypercubeᵀᴹ
5

Iya: GENERATED ALWAYS AS … STORED

Postgres 12 menambahkan fungsionalitas untuk kolom yang dihasilkan, seperti yang disebutkan dalam SQL: 2003 .

Nilai dihasilkan pada saat suatu INSERTatauUPDATE , kemudian disimpan dengan baris seperti nilai lainnya.

Yang dihasilkan harus didasarkan pada kolom dasar dari tabel yang sama, atau pada fungsi yang tidak berubah .

Sintaksnya sederhana, klausa pada CREATE TABLE:

GENERATED ALWAYS AS ( generation_expr ) STORED 

Contoh:

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

Fitur:

  • Dapat diindeks.
  • Bagian dari standar SQL.

Peringatan:

  • Berdasarkan kolom dari tabel yang sama (bukan tabel terkait)
  • Tidak diizinkan mempartisi (tidak dapat menjadi bagian dari kunci partisi)
  • Data selalu ditulis ke baris, mengambil ruang dalam penyimpanan
    • Fitur di masa depan mungkin menawarkan VIRTUAL untuk nilai yang dihitung secara langsung tanpa penyimpanan
  • Satu generasi dalam (gunakan kolom dasar, bukan kolom lain yang dihasilkan)
  • Tidak ada DIHASILKAN OLEH DEFAULT (Anda tidak dapat mengesampingkan nilai)
  • Tidak dapat mengakses gen-col di SEBELUM pemicu (nilai belum ditentukan)
  • Fungsi harus tidak berubah

Lihat:

Basil Bourque
sumber
Terima kasih atas informasinya. Saya melihat bahwa versi 12 belum sepenuhnya dirilis, tetapi saya menantikannya. Saya perhatikan bahwa PostgreSQL menggunakan sintaksis yang lebih standar, tetapi sebaliknya sama dengan MSSQL. Saya menemukan spesifikasi SQL2003 di sini: sigmodrecord.org/publications/sigmodRecord/0403/… . Saya selalu mengatakan bahwa SQL adalah standar yang sangat lambat, dan implementasi DBMS bahkan lambat.
Manngo
0

Tergantung pada kasus penggunaan Anda, Anda bisa mencapai perilaku semacam ini dengan mendeklarasikan kolom baru dan mengisinya dengan pemicu pada sisipan / pembaruan.

Saya akan menggunakan jawaban di atas jika mungkin untuk menghindari duplikasi data yang dapat diturunkan dari apa yang sudah Anda miliki, tetapi itu memang melakukan trik dan bisa berguna untuk bidang turunan intensif komputasi yang ingin Anda hitung sekali dan simpan.

Saya menganggap pendekatan ini untuk menangani masalah di mana saya kadang-kadang hanya memiliki 15 digit kunci 18 digit (3 digit terakhir hanya sebuah checksum) tetapi ingin dapat menegakkan hubungan kunci asing.

Dokumen PG tentang pemicu: https://www.postgresql.org/docs/9.6/sql-createtrigger.html

Contoh W3: https://www.w3resource.com/PostgreSQL/postgresql-triggers.php

Allen Phelps
sumber