Saya sedang menulis pemicu validasi. Pemicu harus memvalidasi bahwa jumlah array sama dengan bidang lain. Karena saya memiliki banyak contoh validasi ini, saya ingin menulis satu prosedur dan membuat beberapa pemicu, masing-masing dengan set bidang yang berbeda untuk diperiksa.
Misalnya, saya memiliki skema berikut:
CREATE TABLE daily_reports(
start_on date
, show_id uuid
, primary key(start_on, show_id)
-- _graph are hourly values, while _count is total for the report
, impressions_count bigint not null
, impressions_graph bigint[] not null
-- interactions_count, interactions_graph
-- twitter_interactions_count, twitter_interactions_graph
);
Validasi harus mengkonfirmasi hal itu impressions_count = sum(impressions_graph)
.
Saya macet karena saya tidak tahu cara mengakses bidang secara dinamis NEW
dari dalam plpgsql:
CREATE FUNCTION validate_sum_of_array_equals_other() RETURNS TRIGGER AS $$
DECLARE
total bigint;
array_sum bigint;
BEGIN
-- TG_NARGS = 2
-- TG_ARGV[0] = 'impressions_count'
-- TG_ARGV[1] = 'impressions_graph'
-- How to access impressions_count and impressions_graph from NEW?
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER validate_daily_reports_impressions
ON daily_reports BEFORE INSERT OR UPDATE
FOR EACH ROW EXECUTE
validate_sum_of_array_equals_other('impressions_count', 'impressions_graph');
Saya mencoba Menjalankan Perintah Dinamis dengan melakukan EXECUTE 'SELECT $1 FROM NEW' INTO total USING TG_ARGV[0]
, tetapi PL / PGsql mengeluh bahwa BARU adalah hubungan yang tidak diketahui.
Saya secara khusus menargetkan PostgreSQL 9.1.
postgresql
trigger
plpgsql
composite-types
François Beausoleil
sumber
sumber
NEW
saat ini adalah dengan menggunakanhstore(NEW)
dan kemudian mengakses bidang sebagaihstore
nilai yang dikunci dengan nama kolom. Yang menyebalkan, karena mereka semua dilemparkan ketext
dan jika Anda ingin bekerja dengan mereka dalam tipe asli Anda, Anda harus melemparkan mereka kembali. Sebagai alternatif, Anda dapat menulis pemicu dalam bahasa prosedural lain seperti PL / Python yang memiliki dukungan yang lebih baik untuk akses rekaman dinamis.Jawaban:
Sebenarnya, karena
NEW
merupakan tipe komposit yang terdefinisi dengan baik, Anda dapat mengakses kolom apa saja dengan notasi atribut sederhana dan sederhana. SQL sendiri tidak memungkinkan pengidentifikasi dinamis (nama tabel atau kolom dll.). Tetapi Anda dapat menggunakan SQL dinamis denganEXECUTE
fungsi PL / pgSQL.Demo
Para pemain
text
adalah opsional. Menggunakannya, karena bekerja secara universal. Jika Anda tahu tipenya, Anda dapat bekerja tanpa ...Menggunakan
format()
dengan%s
, karena pengidentifikasi sudah lolos pada saat itu.Lain, gunakan
format()
dengan%I
untuk melindungi terhadap injeksi SQL.Atau , di Postgres 9.3 atau lebih baru, Anda dapat mengonversi
NEW
ke JSON denganto_json()
dan mengakses kolom sebagai kunci:Karena nama kolom tidak digabungkan menjadi string SQL, injeksi SQL tidak mungkin, dan nama tidak perlu diloloskan.
db <> bermain-main di sini (dengan
EXCEPTION
alih - alihNOTICE
membuat efeknya terlihat).Terkait:
sumber