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