PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

plpgsql - menggunakan nama tabel dinamis dalam pernyataan pernyataan

Penting untuk memahami sifat utama dari kelima jenis data / simbol yang berbeda ini :

1. 'my_tbl'

Sebuah literal string dari unknown ketik . Ketika digunakan dalam SQL (tertanam dalam kode plpgsql atau tidak), itu dipaksa ke jenis yang berasal dari konteks . Jika jenisnya tidak dapat ditentukan, pemeran eksplisit mungkin diperlukan. Seperti:'my_tbl'::text .

2. 'my_tbl'::text

String literal yang sama dilemparkan ke ketik text . Itu bisa menampung nama tabel, tapi sebenarnya hanya teks.

3. 'my_tbl'::regclass

pengidentifikasi objek (OID) untuk kelas registered yang terdaftar . Ini ditampilkan dan dapat dimasukkan sebagai string yang mewakili nama objek yang valid ('my_tbl' ). Output secara otomatis memenuhi syarat skema ('my_schema.my_tbl' ) dan / atau tanda kutip ganda ('"mY_TbL"' ) jika itu akan menjadi ambigu atau ilegal. Ini bisa berupa tabel regular biasa , urutan , lihat , tampilan yang terwujud , jenis komposit dll. Detail dalam jawaban terkait ini:

4. my_tbl_var my_tbl (kependekan dari my_tbl_var my_tbl%ROWTYPE )

Dalam DECLARE bagian dari blok kode plpgsql yang merupakan deklarasi variabel dengan terkenal jenis baris (alias tipe komposit). Jenis harus didaftarkan di tabel sistem pg_class (sama seperti dengan regclass variabel). Ini bukan OID dari objek yang direferensikan, tetapi tipe barisnya yang sebenarnya. my_tbl_var dan my_tbl keduanya pengidentifikasi di sini dan tidak dapat diparameterisasi. Anda juga dapat mentransmisikan baris atau rekaman apa pun secara langsung:(123, 'foo')::my_tbl

5. my_tbl_var record

Dalam DECLARE bagian dari blok kode plpgsql yang merupakan deklarasi anonim rekaman . Pada dasarnya, placeholder untuk tipe baris yang belum diketahui / dengan struktur yang belum ditentukan. Ini dapat digunakan di sebagian besar tempat jenis baris dapat digunakan. Tetapi Anda tidak dapat mengakses bidang darinya sebelum variabel record ditetapkan.

Anda membingungkan 1. , 3. dan 4. dan selesaikan dengan menggunakan 5. sebagai gantinya.
Tapi ada lebih banyak kesalahan di sini:

  • Anda memilih seluruh tabel, tetapi variabel baris (catatan) hanya dapat menampung satu baris dalam satu waktu. Jadi hanya yang pertama ditugaskan dan dikembalikan. Meskipun tidak ada ORDER BY klausa, hasilnya arbitrer dan dapat berubah sewaktu-waktu. Perangkap jahat.

  • Karena Anda sekarang menggunakan record ketik, Anda perlu memastikan itu telah ditetapkan sebelum Anda dapat menjalankan tes di bidangnya, atau Anda akan mendapatkan pengecualian untuk tabel kosong. Dalam kasus Anda, centang record_var IS NULL hampir melakukan pekerjaan yang sama. Tetapi ada kasus sudut untuk baris dengan NULL di semua bidang:lalu record_var IS NULL mengevaluasi menjadi benar. Bahkan lebih sulit untuk pengujian IS NOT NULL . Detailnya di sini:

    Saya menambahkan demo ke SQL fiddle di bawah.

  • Fungsi mengembalikan skalar tunggal (boolean ) nilai. Gunakan:

    RETURN false;
    

    Alih-alih:

    RETURN QUERY SELECT false;

Fungsi

CREATE FUNCTION check_valid(_tbl regclass)
  RETURNS bool AS
$func$
DECLARE
   r record;
   _row_ct int;
BEGIN
   EXECUTE '
   SELECT is_valid, hit_count, hit_limit
   FROM  ' || _tbl || '
   ORDER  <whatever>
   LIMIT  1'            -- replace <whatever> with your sort criteria
   INTO r;              -- only needed columns

   GET DIAGNOSTICS _row_ct = ROW_COUNT;

   IF _row_ct = 0 THEN  -- necessary, because r may not be assigned
      RETURN false;
   ELSIF NOT r.is_valid OR r.hit_count > r.hit_limit THEN
      RETURN false;
   END IF;

   RETURN true;
END
$func$  LANGUAGE plpgsql;

SQL Fiddle (dengan dua varian fungsi dan demo untuk baris IS NULL).

Poin utama

  • Gunakan GET DIAGNOSTICS untuk mengetahui apakah ada baris yang ditemukan dalam pernyataan dinamis dengan EXECUTE .

  • IF ekspresi dapat disederhanakan.

  • Parameternya bertipe regclass , bukan hanya nama tabel. Saya tidak akan menggunakan nama "tablename" yang menyesatkan untuk parameter ini. Itu hanya menambah kebingungan awal Anda. Menyebutnya _tbl sebagai gantinya.

Jika Anda ingin juga kembali satu set tipe baris variabel:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL menemukan semua kemungkinan kombinasi (permutasi) dalam kueri rekursif

  2. Opsi Multitenancy untuk PostgreSQL

  3. Postgres:Kesalahan menggunakan GROUP BY dan ORDER (di heroku)

  4. Postgres - Ubah daftar adjacency menjadi objek JSON bersarang

  5. Docker &Postgres:Gagal mengikat alamat tcp 0.0.0.0:5432 yang sudah digunakan