Sementara jawaban @ Gary secara teknis benar, ia gagal menyebutkan bahwa PostgreSQL benar dukung formulir ini:
UPDATE tbl
SET (col1, col2, ...) = (expression1, expression2, ..)
Baca manual di UPDATE sekali lagi.
Masih sulit untuk menyelesaikannya dengan SQL dinamis. Karena Anda tidak menentukan, saya mengasumsikan kasus sederhana di mana tampilan terdiri dari kolom yang sama dengan tabel yang mendasarinya.
CREATE VIEW tbl_view AS SELECT * FROM tbl;
Masalah
-
Catatan khusus
NEWtidak terlihat di dalamEXECUTE. Saya lulusNEWsebagai parameter tunggal denganUSINGklausaEXECUTE. -
Seperti yang telah dibahas,
UPDATEdengan formulir daftar membutuhkan nilai individu . Saya menggunakan subpilihan untuk membagi catatan menjadi kolom individual:UPDATE ... FROM (SELECT ($1).*) x(Kurung di sekitar
$1tidak opsional.) Ini memungkinkan saya untuk menggunakan dua daftar kolom yang dibuat denganstring_agg()dari tabel katalog:satu dengan dan satu tanpa kualifikasi tabel. -
Tidak mungkin menetapkan nilai baris secara keseluruhan ke masing-masing kolom. Panduan:
Menurut standar, nilai sumber untuk sub-daftar yang dikurung dari nama kolom target dapat berupa ekspresi bernilai baris apa pun yang menghasilkan jumlah kolom yang benar. PostgreSQL hanya mengizinkan nilai sumber menjadi konstruktor baris atau sub-
SELECT. -
INSERTdiimplementasikan lebih sederhana. Dengan asumsi struktur tampilan dan tabel identik, saya menghilangkan daftar definisi kolom. (Dapat ditingkatkan, lihat di bawah.)
Solusi
Saya membuat sejumlah pembaruan pada pendekatan Anda untuk membuatnya bersinar.
Fungsi pemicu untuk UPDATE :
CREATE OR REPLACE FUNCTION f_trg_up()
RETURNS TRIGGER AS
$func$
DECLARE
tbl text := quote_ident(TG_TABLE_SCHEMA) || '.'
|| quote_ident(substring(TG_TABLE_NAME from '(.+)_view$'));
cols text;
vals text;
BEGIN
SELECT INTO cols, vals
string_agg(quote_ident(attname), ', ')
,string_agg('x.' || quote_ident(attname), ', ')
FROM pg_attribute
WHERE attrelid = tbl::regclass
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0; -- no system columns
EXECUTE format('
UPDATE %s t
SET (%s) = (%s)
FROM (SELECT ($1).*) x
WHERE t.id = ($2).id'
, tbl, cols, vals) -- assuming unique "id" in every table
USING NEW, OLD;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Fungsi pemicu untuk INSERT :
CREATE OR REPLACE FUNCTION f_trg_ins()
RETURNS TRIGGER AS
$func$
DECLARE
tbl text := quote_ident(TG_TABLE_SCHEMA) || '.'
|| quote_ident(substring(TG_TABLE_NAME from '(.+)_view$'));
BEGIN
EXECUTE 'INSERT INTO ' || tbl || ' SELECT ($1).*'
USING NEW;
RETURN NEW; -- don't return NULL unless you know what you're doing
END
$func$ LANGUAGE plpgsql;
Pemicu:
CREATE TRIGGER trg_instead_up
INSTEAD OF UPDATE ON a_view
FOR EACH ROW EXECUTE PROCEDURE f_trg_up();
CREATE TRIGGER trg_instead_ins
INSTEAD OF INSERT ON a_view
FOR EACH ROW EXECUTE PROCEDURE f_trg_ins();
SQL Fiddle mendemonstrasikan INSERT dan UPDATE .
Poin utama
-
Sertakan nama skema untuk membuat referensi tabel tidak ambigu. Mungkin ada beberapa contoh nama tabel yang sama dalam database yang sama dalam beberapa skema!
-
Kueri
pg_attributebukannyainformation_schema.columns. Itu kurang portabel, tapi banyak lebih cepat dan memungkinkan saya untuk menggunakan table-OID.- Cara memeriksa apakah ada tabel dalam skema tertentu
-
Nama tabel TIDAK aman terhadap SQLi ketika ditangani sebagai string seperti dalam membangun kueri untuk SQL dinamis. Melarikan diri dengan
quote_ident()atauformat()atau dengan tipe pengidentifikasi objek. Ini termasuk variabel fungsi pemicu khususTG_TABLE_SCHEMAdanTG_TABLE_NAME! -
Transmisikan ke tipe pengenal objek
regclassuntuk menegaskan bahwa nama tabel valid dan mendapatkan OID untuk pencarian katalog. -
Secara opsional gunakan
format()untuk membangun string kueri dinamis dengan aman. -
Tidak perlu SQL dinamis untuk kueri pertama di tabel katalog. Lebih cepat, lebih sederhana.
-
Gunakan
RETURN NEWbukannyaRETURN NULLdalam fungsi pemicu ini kecuali Anda tahu apa yang Anda lakukan. (NULLakan membatalkanINSERTuntuk baris saat ini.) -
Versi sederhana ini mengasumsikan bahwa setiap tabel (dan tampilan) memiliki kolom unik bernama
id. Versi yang lebih canggih mungkin menggunakan kunci utama secara dinamis. -
Fungsi untuk
UPDATEmemungkinkan kolom tampilan dan tabel berada dalam urutan apa pun , asalkan himpunannya sama. Fungsi untukINSERTmengharapkan kolom tampilan dan tabel berada dalam urutan yang sama . Jika Anda ingin mengizinkan urutan sewenang-wenang, tambahkan daftar definisi kolom keINSERTperintah, seperti denganUPDATE. -
Versi yang diperbarui juga mencakup perubahan pada
idkolom dengan menggunakanOLDtambahan.