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:
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?
Apa perbedaan antara dua kasus yang mengarah pada perilaku yang berbeda?
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 validJawaban:
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. JadiSELECT my_SRF()
menghasilkan sama sepertiSELECT * FROM my_SRF()
untuk kasus sederhana. Manual tentang Fungsi 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
SELECT
daftar. Ini akan berubah dengan Postgres 10 untuk selamanya, meskipun:Cara yang aman dan tidak membingungkan untuk kedua kasus adalah dengan memindahkan fungsi SRF ke
FROM
klausa. GunakanLATERAL
gabungan jika Anda perlu merujuk ke kolom dari tabel lain. Manual menyarankan:sumber