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

Tentukan nama tabel dan kolom sebagai argumen dalam fungsi plpgsql?

Anda harus bertahan melawan injeksi SQL setiap kali Anda mengubah input pengguna menjadi kode. Itu termasuk nama tabel dan kolom yang berasal dari katalog sistem atau dari input pengguna langsung. Dengan cara ini Anda juga mencegah pengecualian sepele dengan pengidentifikasi non-standar. Pada dasarnya ada tiga metode bawaan:

1. format()

Kueri pertama, dibersihkan:

CREATE OR REPLACE FUNCTION foo(_t text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('
   ALTER TABLE %I ADD COLUMN c1 varchar(20)
                , ADD COLUMN c2 varchar(20)', _t);
END
$func$;

format() membutuhkan Postgres 9.1 atau lebih baru. Gunakan dengan %I penentu format.

Nama tabel saja mungkin ambigu. Anda mungkin harus memberikan nama skema untuk menghindari perubahan tabel yang salah secara tidak sengaja. Terkait:

  • MASUKKAN dengan nama tabel dinamis dalam fungsi pemicu
  • Bagaimana search_path mempengaruhi resolusi pengenal dan "skema saat ini"

Selain:menambahkan beberapa kolom dengan satu ALTER TABLE perintah lebih murah.

2. regclass

Anda juga dapat menggunakan pemeran ke kelas terdaftar (regclass ) untuk kasus khusus ada nama tabel. Opsional memenuhi syarat skema. Ini gagal segera dan anggun untuk nama tabel yang tidak valid dan terlihat oleh pengguna yang menelepon. Kueri pertama dibersihkan dengan cast ke regclass :

CREATE OR REPLACE FUNCTION foo(_t regclass)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE 'ALTER TABLE ' || _t || ' ADD COLUMN c1 varchar(20)
                                   , ADD COLUMN c2 varchar(20)';
END
$func$;

Telepon:

SELECT foo('table_name');

Atau:

SELECT foo('my_schema.table_name'::regclass);

Selain:pertimbangkan untuk hanya menggunakan text bukannya varchar(20) .

3. quote_ident()

Kueri ke-2 dibersihkan:

CREATE OR REPLACE FUNCTION foo(_t regclass, _c text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE 'UPDATE ' || _t    -- sanitized with regclass
        || ' SET ' || quote_ident(_c) || ' = ''This is a test''';
END
$func$;

Untuk beberapa penggabungan / interpolasi, format() lebih bersih...

Jawaban terkait:

  • Nama tabel sebagai parameter fungsi PostgreSQL
  • Fungsi postgres vs kueri yang disiapkan

Peka huruf besar kecil!

Ketahuilah bahwa pengidentifikasi yang tidak dikutip adalah bukan dilemparkan ke huruf kecil di sini. Saat digunakan sebagai pengidentifikasi dalam SQL [Postgres dilemparkan ke huruf kecil secara otomatis][7]. Tapi di sini kita melewati string untuk SQL dinamis. Saat lolos seperti yang ditunjukkan, pengidentifikasi kasus CaMel (seperti UserS ) akan dipertahankan dengan tanda kutip ganda ("UserS" ), sama seperti nama non-standar lainnya seperti "name with space" "SELECT" dll. Oleh karena itu, nama peka huruf besar/kecil dalam konteks ini.

Saran saya adalah menggunakan pengidentifikasi huruf kecil yang sah secara eksklusif dan jangan pernah khawatir tentang itu.

Selain:tanda kutip tunggal untuk nilai, tanda kutip ganda untuk pengidentifikasi. Lihat:

  • https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Impor Perpustakaan psycopg2 tidak dimuat:libssl.1.0.0.dylib

  2. Pemulihan cadangan PostgreSQL dan TimescaleDB menggunakan ClusterControl CLI

  3. Postgres - versi terakhir 0.14.0 dari permata pg memberikan kesalahan

  4. Mengapa urutan id SQL tidak sinkron (khususnya menggunakan Postgres)?

  5. OFFSET vs. ROW_NUMBER()