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

Bagaimana cara menggunakan input teks sebagai nama kolom dalam fungsi Postgres?

Melewati beberapa nama kolom sebagai string gabungan untuk eksekusi dinamis sangat membutuhkan dekontaminasi. Saya menyarankan VARIADIC sebagai gantinya, dengan pengidentifikasi yang dikutip dengan benar (menggunakan quote_ident() dalam hal ini):

CREATE OR REPLACE FUNCTION select_by_txt(z int, x int, y int, VARIADIC cols text[] = NULL, OUT res text)
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format(
$$
SELECT ST_AsMVT(mvtgeom, 'public.select_by_txt')
FROM  (
   SELECT ST_AsMVTGeom(ST_Transform(t.geom, 3857), bounds.geom) AS geom%s
   FROM   table1 t
   JOIN  (SELECT ST_TileEnvelope($1, $2, $3)) AS bounds(geom)
          ON ST_Intersects(t.geom, ST_Transform(bounds.geom, 4326))
   ) mvtgeom
$$, (SELECT ', ' || string_agg(quote_ident (col), ', ') FROM unnest(cols) col)
   )
   INTO  res
   USING z, x, y;
END
$func$;

db<>fiddle di sini

Penentu format %I untuk format() berurusan dengan tunggal pengenal. Anda harus melakukan lebih banyak pekerjaan untuk banyak pengidentifikasi, terutama untuk sejumlah variabel pengidentifikasi 0-n. Implementasi ini mengutip setiap nama kolom, dan hanya menambahkan , jika ada nama kolom yang telah dilewati. Jadi ini berfungsi untuk setiap masukan yang memungkinkan , bahkan tidak ada masukan sama sekali. Catatan VARIADIC cols text[] = NULL sebagai parameter input terakhir dengan NULL sebagai nilai default:

Terkait:

Nama kolom peka huruf besar/kecil dalam konteks ini!

Panggil contoh Anda (penting!):

SELECT select_by_txt(10,32,33,'col1', 'col2');

Sintaks alternatif:

SELECT select_by_txt(10,32,33, VARIADIC '{col1,col2}');

Panggilan yang lebih terbuka, dengan nama kolom ketiga dan niat jahat (meskipun sia-sia):

SELECT select_by_txt(10,32,33,'col1', 'col2', $$col3'); DROP TABLE table1;--$$);

Tentang nama kolom ketiga yang aneh dan injeksi SQL:

Tentang VAIRADIC parameter:

Menggunakan OUT parameter untuk kesederhanaan. Itu benar-benar opsional. Lihat:

Apa yang saya tidak akan lakukan

Jika Anda benar-benar memercayai input sebagai daftar dengan format 1 atau lebih nama kolom yang valid setiap saat - dan Anda menegaskan bahwa ...

Anda bisa sederhanakan:

CREATE OR REPLACE FUNCTION select_by_txt(z int, x int, y int, cols text, OUT res text)
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format(
$$
SELECT ST_AsMVT(mvtgeom, 'public.select_by_txt')
FROM  (
   SELECT ST_AsMVTGeom(ST_Transform(t.geom, 3857), bounds.geom) AS geom, %s
   FROM   table1 t
   JOIN  (SELECT ST_TileEnvelope($1, $2, $3)) AS bounds(geom)
          ON ST_Intersects(t.geom, ST_Transform(bounds.geom, 4326))
   ) mvtgeom
$$, cols
   )
   INTO  res
   USING z, x, y;
END
$func$;

(Bagaimana Anda bisa begitu yakin bahwa input akan selalu dapat diandalkan?)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara menambahkan kunci utama peningkatan otomatis ke tabel yang ada, di PostgreSQL?

  2. Pernyataan BREAK di PL/pgSQL

  3. Menginstal pg -v 0.17.1

  4. Bagaimana saya bisa mempercepat operasi pembaruan/penggantian di PostgreSQL?

  5. Operator tidak ada:integer =integer[] dalam kueri dengan APAPUN