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

Nama tabel sebagai parameter fungsi PostgreSQL

Ini dapat lebih disederhanakan dan ditingkatkan:

CREATE OR REPLACE FUNCTION some_f(_tbl regclass, OUT result integer)
    LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('SELECT (EXISTS (SELECT FROM %s WHERE id = 1))::int', _tbl)
   INTO result;
END
$func$;

Panggil dengan nama yang memenuhi syarat skema (lihat di bawah):

SELECT some_f('myschema.mytable');  -- would fail with quote_ident()

Atau:

SELECT some_f('"my very uncommon table name"');

Poin utama

Gunakan OUT parameter untuk menyederhanakan fungsi. Anda dapat langsung memilih hasil SQL dinamis ke dalamnya dan selesai. Tidak perlu variabel dan kode tambahan.

EXISTS melakukan apa yang Anda inginkan. Anda mendapatkan true jika baris ada atau false sebaliknya. Ada berbagai cara untuk melakukan ini, EXISTS biasanya paling efisien.

Sepertinya Anda menginginkan bilangan bulat kembali, jadi saya melemparkan boolean hasil dari EXISTS ke integer , yang menghasilkan persis seperti yang Anda miliki. Saya akan mengembalikan boolean sebagai gantinya.

Saya menggunakan jenis pengenal objek regclass sebagai tipe input untuk _tbl . Itu melakukan segalanya quote_ident(_tbl) atau format('%I', _tbl) akan melakukannya, tetapi lebih baik, karena:

  • .. mencegah injeksi SQL juga.

  • .. segera gagal dan lebih anggun jika nama tabel tidak valid / tidak ada / tidak terlihat oleh pengguna saat ini. (Sebuah regclass parameter hanya berlaku untuk yang ada tabel.)

  • .. ini bekerja dengan nama tabel yang memenuhi syarat skema, di mana quote_ident(_tbl) biasa atau format(%I) akan gagal karena mereka tidak dapat menyelesaikan ambiguitas. Anda harus melewati dan keluar dari skema dan nama tabel secara terpisah.

Ini hanya berfungsi untuk yang sudah ada tabel, tentu saja.

Saya masih menggunakan format() , karena menyederhanakan sintaks (dan untuk mendemonstrasikan cara penggunaannya), tetapi dengan %s bukannya %I . Biasanya, kueri lebih kompleks sehingga format() membantu lebih banyak. Untuk contoh sederhana, kita juga bisa menggabungkan:

EXECUTE 'SELECT (EXISTS (SELECT FROM ' || _tbl || ' WHERE id = 1))::int'

Tidak perlu melakukan kualifikasi tabel id kolom sementara hanya ada satu tabel di FROM daftar. Tidak ada ambiguitas yang mungkin terjadi dalam contoh ini. (Dinamis) Perintah SQL di dalam EXECUTE memiliki cakupan terpisah , variabel atau parameter fungsi tidak terlihat di sana - berlawanan dengan perintah SQL biasa di badan fungsi.

Inilah mengapa Anda selalu keluar dari input pengguna untuk SQL dinamis dengan benar:

db<>main biola di sini mendemonstrasikan injeksi SQL
sqlfiddle lama



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kapan memilih untuk memperbarui mengunci dan membuka kunci?

  2. Menggunakan kueri Hibernate :titik dua diperlakukan sebagai parameter / keluar dari titik dua

  3. Bagaimana cara membuat enum Java &Postgres bekerja sama untuk pembaruan?

  4. Menggabungkan nilai JSONB di PostgreSQL?

  5. Gabungkan kueri dengan hanya kolom yang memiliki semua nilai dalam klausa `dalam`