Memahami Mengatur Fungsi Pengembalian (SRF) dalam Daftar SELECT


8

Mengapa ada perbedaan perilaku antara menggunakan Set Returning Function (SRF) dalam daftar SELECT vs menggunakan SRF dalam klausa FROM?

Misalnya, untuk SRF sederhana yang mengembalikan 2 baris:

CREATE OR REPLACE FUNCTION gen_series(out integer, out int)
  RETURNS SETOF record AS $$
  SELECT 1,1
  UNION
  SELECT 2,2;
$$ LANGUAGE SQL;

SELECT gen_series(); mengembalikan dua baris kolom tunggal yang masing-masing berisi catatan:

=>  gen_series 
------------
 (1,1)
 (2,2)
(2 rows)

Sedangkan SELECT * FROM gen_series();mengembalikan dua baris dengan catatan diperluas:

=>  column1 | column2 
---------+---------
       1 |       1
       2 |       2
(2 rows)

Sebagai perbandingan, jika SRF mengembalikan satu kolom, maka memanggil SRF dalam klausa SELECT atau FROM tidak ada bedanya. misalnya:

=> SELECT generate_series(1,2);
 generate_series 
-----------------
               1
               2
(2 rows)

=> SELECT * FROM generate_series(1,2);
 generate_series 
-----------------
               1
               2
(2 rows)

Pertanyaan saya adalah:

  1. Saya tidak begitu mengerti mengapa dalam kasus kedua, perilaku SRF berbeda dari kasus pertama hanya karena tabel yang dikembalikan memiliki satu kolom. Apakah perilaku ini benar-benar konsisten dalam hal jenis, tupel, dan set?

  2. Apa perbedaan antara dua kasus yang mengarah pada perilaku yang berbeda?

  3. SRF dapat digunakan sebagai tabel seperti yang ditunjukkan di atas, tetapi dapatkah tabel juga digunakan untuk menggantikan SRF? misalnya

    SELECT my_table; 

Rupanya, ini tidak bisa dilakukan, tetapi mengapa SELECT my_SRF();mungkin, padahal SELECT my_table;tidak diizinkan (dalam hal hubungan dan matematika)?


SELECT my_table;bukan sintaks yang valid
Mladen Uzelac

Jawaban:


3

Postgres memperlakukan kasus sederhana secara berbeda. Beberapa kolom diperlakukan sebagai tipe komposit (baris tabel), yang hanya didekomposisi dengan SELECT * FROM ..., sedangkan satu kolom tipe skalar diperlakukan hanya seperti itu, tidak ada pembungkus tipe komposit yang ditambahkan. Jadi SELECT my_SRF()menghasilkan sama seperti SELECT * FROM my_SRF()untuk kasus sederhana. Manual tentang Fungsi Tabel :

Fungsi tabel adalah fungsi yang menghasilkan satu set baris, terdiri dari tipe data dasar (tipe skalar) atau tipe data komposit (baris tabel).

Saya setuju ini membingungkan, dan Anda bukan orang pertama yang bingung. (Tapi pertimbangkan alternatifnya: menambahkan pembungkus tipe komposit di sekitar satu kolom bahkan mungkin lebih membingungkan.)

Tetapi tidak membingungkan seperti apa yang terjadi ketika Anda menggabungkan beberapa fungsi SRF dalam SELECTdaftar. Ini akan berubah dengan Postgres 10 untuk selamanya, meskipun:

Cara yang aman dan tidak membingungkan untuk kedua kasus adalah dengan memindahkan fungsi SRF ke FROMklausa. Gunakan LATERALgabungan jika Anda perlu merujuk ke kolom dari tabel lain. Manual menyarankan:

The LATERALsintaks menghasilkan hasil yang kurang mengejutkan saat memanggil beberapa fungsi set-kembali, dan biasanya harus digunakan sebagai gantinya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.