Deklarasikan variabel tipe tabel dalam PL / pgSQL

8

Saya bertanya-tanya apakah ada cara untuk mendeklarasikan variabel tabel tipe dalam PL / pgSQL untuk menyimpan hasil permintaan? Misalnya bagaimana saya bisa mengekspresikan sesuatu seperti:

q1 = select * from foo;
q2 = select * from bar;
for t1 in q1:
  for t2 in q2:
    -- do something with t1 and t2

Saya melihat ke dalam membangun kembali berikutnya tetapi yang tampaknya hanya mampu menangani nilai kembali.

JRR
sumber
2
PL / SQL => Oracle, PgPL / SQL => PostgreSQL. Anda bekerja dengan yang mana?
Mat
@Mat: Ini PL / pgSQL , btw.
Erwin Brandstetter

Jawaban:

12

Di PostgreSQL , setiap nama tabel berfungsi sebagai nama tipe untuk tipe baris (alias tipe komposit ) secara otomatis - bukan tipe tabel, tidak ada "tipe tabel" atau "variabel tabel" di Postgres ( tetapi ada tabel yang diketik ).
Jadi Anda bisa mendeklarasikan variabel jenis itu di PL/pgSQL.

CREATE FUNCTION foo()
 RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
  q1 foo;  -- "foo" ...
  q2 bar;  -- ... and "bar" are existing (visible) table names
BEGIN

FOR q1 IN 
   SELECT * from foo
LOOP
   FOR q2 IN 
      SELECT * from bar
   LOOP
       -- do something with q1 and q2
       -- since q1 and q2 are well known types, you can access columns
       -- with attribute notation. Like: q1.col1
   END LOOP;
END LOOP;

END
$func$

Sebuah FORlingkaran bekerja dengan built-in kursor. Ada juga kursor eksplisit di plpgsql.

Anda juga bisa mendeklarasikan variabel dari tipe generik record. Itu dapat mengambil semua jenis baris saat penugasan secara otomatis. Tetapi aturan khusus berlaku. Pastikan untuk mengikuti tautan dan membaca bab manual!

Meskipun sering kali nyaman untuk memiliki fungsi kembali SETOF <table name>, mengembalikan SETOF recordtidak nyaman. Sistem tidak tahu apa fungsi yang dikembalikan dengan cara ini dan Anda harus menambahkan daftar definisi kolom dengan setiap panggilan. Yang merupakan rasa sakit. Detail tentang fungsi tabel dalam manual .

Seringkali ada solusi yang lebih efisien dengan SQL biasa. Looping adalah ukuran upaya terakhir, ketika Anda dapat melakukan hal-hal dalam satu pemindaian di mana Anda akan memerlukan banyak pemindaian dalam SQL murni.

Erwin Brandstetter
sumber
2
Perhatikan juga bahwa jika Anda ingin mengembalikan jenis tabel Anda bisa mengatakan sesuatu sepertiCREATE FUNCTION footest() RETURNS SETOF foo LANGUAGE PLPGSQL AS $$...
Chris Travers
Lalu mengapa kita sama sekali memiliki fitur "tipe komposit" jika kita dapat membuat tabel sebagai gantinya, tanpa batasan yang diterapkan pada tipe komposit (tanpa kendala, dll)? Satu-satunya cara yang berarti untuk menggunakan tipe komposit yang saya lihat adalah mengembalikan beberapa (atau beberapa) parameter dari fungsi alih-alih membuat seluruh tabel untuk itu.
SaneDeveloper