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

Jangan melakukan apa pun dalam prosedur pemicu

Contoh Anda rusak. Sumber dan target sama di INSERT di pemicu, yang pasti akan memunculkan pelanggaran unik setiap saat (kecuali saat memasukkan NULL) - ditekan oleh ON CONFLICT (test_name2) DO NOTHING , jadi tidak ada yang terjadi di pemicunya.

Anda juga melupakan batasan unik di INSERT asli Anda . Lihat di bawah.

INSERT INTO test2(test_name2)
   VALUES(NEW.test_name2)

...

CREATE TRIGGER trigger_test
AFTER INSERT
ON test2

Mulailah dengan penyiapan yang tidak terlalu membingungkan:

CREATE TABLE test1 (col1 text UNIQUE);
CREATE TABLE test2 (col2 text UNIQUE);

Dan lebih efisien untuk memindahkan pg_trigger_depth() ke pemicu itu sendiri. Jadi ini akan berhasil, menyalin baris yang dimasukkan ke test1 untuk test2 (dan bukan sebaliknya), hanya untuk pertama tingkat kedalaman pemicu:

CREATE OR REPLACE FUNCTION trig_test()
  RETURNS trigger AS
$func$
BEGIN
   INSERT INTO test2(col2)             -- !!
   VALUES (NEW.col1)                   -- !!
   ON     CONFLICT (col2) DO NOTHING;  -- !!

   RETURN NULL;
END
$func$ LANGUAGE plpgsql;

Saya menyimpannya sebagai AFTER pemicu. Dapat berupa BEFORE pemicu juga, tapi di sana Anda membutuhkan RETURN NEW; .

CREATE TRIGGER trigger_test
AFTER INSERT ON test1                  -- !!
FOR EACH ROW 
WHEN (pg_trigger_depth() < 1)          -- !!
EXECUTE PROCEDURE trig_test();

Mengapa (pg_trigger_depth() < 1) ?

Catatan bahwa Anda menjebak pelanggaran unik di test2 dengan cara ini (tidak ada yang terjadi), tetapi pelanggaran unik di test1 akan tetap memunculkan pengecualian kecuali Anda memiliki ON CONFLICT ... DO NOTHING di sana juga. Tes Anda adalah angan-angan:

Harus:

INSERT INTO test1 values ('test') ON CONFLICT (col1) DO NOTHING;

Alternatif:Rantai dua INSERT dengan CTE

Jika Anda memiliki kendali atas INSERT perintah pada test1 , Anda dapat melakukan ini sebagai ganti pemicu:

WITH ins1 AS (
   INSERT INTO test1(col1)
   VALUES ('foo')                  -- your value goes here
   ON CONFLICT (col1) DO NOTHING
   RETURNING *
   )
INSERT INTO test2(col2)
SELECT col1 FROM ins1
ON CONFLICT (col2) DO NOTHING;

Terkait:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara memasang volume postgresql menggunakan Aws EBS di Kubernete

  2. Variabel lingkungan penulisan Docker

  3. pg_dump:bagaimana cara menginstal di Amazon Linux untuk PostgreSQL 9.5.2?

  4. PostgreSQL - Mendapatkan data statistik

  5. Bagaimana cara menjumlahkan nilai dalam array JSONB di Postgresql?