PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

PostgreSQL में प्रति पंक्ति केवल एक बार आस्थगित ट्रिगर निष्पादित करें

यह एक विकट समस्या है। लेकिन इसे PostgreSQL 9.0 में पेश किए गए प्रति-कॉलम ट्रिगर और सशर्त ट्रिगर निष्पादन के साथ किया जा सकता है ।

आपको प्रति पंक्ति एक "अपडेटेड" फ़्लैग की आवश्यकता है इस समाधान के लिए। एक boolean का प्रयोग करें सादगी के लिए एक ही तालिका में कॉलम। लेकिन यह किसी अन्य तालिका में या प्रति लेनदेन एक अस्थायी तालिका में भी हो सकता है।

महंगा पेलोड प्रति पंक्ति एक बार निष्पादित किया जाता है जहां काउंटर को अपडेट किया जाता है (एक बार या कई बार)।

इसे प्रदर्शन . भी करना चाहिए ठीक है, क्योंकि ...

  • ... यह रूट पर ट्रिगर्स की कई कॉल्स से बचता है (स्केल वेल)
  • ... अतिरिक्त पंक्तियों को नहीं बदलता है (टेबल ब्लोट को छोटा करें)
  • ... को महंगे अपवाद प्रबंधन की आवश्यकता नहीं है।

निम्नलिखित पर विचार करें

डेमो

एक अलग स्कीमा x . के साथ PostgreSQL 9.1 में परीक्षण किया गया परीक्षण वातावरण के रूप में।

टेबल और डमी पंक्तियां

-- DROP SCHEMA x;
CREATE SCHEMA x;

CREATE TABLE x.tbl (
 id int
,counter int
,trig_exec_count integer  -- for monitoring payload execution.
,updated bool);

यह प्रदर्शित करने के लिए दो पंक्तियाँ डालें कि यह कई पंक्तियों के साथ काम करता है:

INSERT INTO x.tbl VALUES
 (1, 0, 0, NULL)
,(2, 0, 0, NULL);

ट्रिगर फ़ंक्शन और ट्रिगर

1.) महंगा पेलोड निष्पादित करें

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_1()
    RETURNS trigger AS
$BODY$
BEGIN

 -- PERFORM some_expensive_procedure(NEW.id);
 -- Update trig_exec_count to count execution of expensive payload.
 -- Could be in another table, for simplicity, I use the same:

UPDATE x.tbl t
SET    trig_exec_count = trig_exec_count + 1
WHERE  t.id = NEW.id;

RETURN NULL;  -- RETURN value of AFTER trigger is ignored anyway

END;
$BODY$ LANGUAGE plpgsql;

2.) पंक्ति को अद्यतन के रूप में चिह्नित करें।

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_2()
    RETURNS trigger AS
$BODY$
BEGIN

UPDATE x.tbl
SET    updated = TRUE
WHERE  id = NEW.id;
RETURN NULL;

END;
$BODY$ LANGUAGE plpgsql;

3.) "अपडेटेड" फ़्लैग रीसेट करें।

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_3()
    RETURNS trigger AS
$BODY$
BEGIN

UPDATE x.tbl
SET    updated = NULL
WHERE  id = NEW.id;
RETURN NULL;

END;
$BODY$ LANGUAGE plpgsql;

ट्रिगर नाम प्रासंगिक हैं! उसी घटना के लिए बुलाया जाता है, उन्हें वर्णानुक्रम में निष्पादित किया जाता है।

1.) पेलोड, अगर अभी तक "अपडेट" नहीं हुआ है:

CREATE CONSTRAINT TRIGGER upaft_counter_change_1
    AFTER UPDATE OF counter ON x.tbl
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
    WHEN (NEW.updated IS NULL)
    EXECUTE PROCEDURE x.trg_upaft_counter_change_1();

2.) पंक्ति को अद्यतन के रूप में फ़्लैग करें, यदि अभी तक "अपडेट" नहीं किया गया है:

CREATE TRIGGER upaft_counter_change_2   -- not deferred!
    AFTER UPDATE OF counter ON x.tbl
    FOR EACH ROW
    WHEN (NEW.updated IS NULL)
    EXECUTE PROCEDURE x.trg_upaft_counter_change_2();

3.) ध्वज रीसेट करें। ट्रिगर की स्थिति के कारण कोई अंतहीन लूप नहीं है।

CREATE CONSTRAINT TRIGGER upaft_counter_change_3
    AFTER UPDATE OF updated ON x.tbl
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
    WHEN (NEW.updated)                 --
    EXECUTE PROCEDURE x.trg_upaft_counter_change_3();

परीक्षा

UPDATE चलाएं &SELECT आस्थगित प्रभाव देखने के लिए अलग से। यदि एक साथ (एक लेन-देन में) निष्पादित किया जाता है तो चयन नया tbl.counter . दिखाएगा लेकिन पुराना tbl2.trig_exec_count

UPDATE x.tbl SET counter = counter + 1;

SELECT * FROM x.tbl;

अब, काउंटर को कई बार अपडेट करें (एक लेनदेन में)। पेलोड केवल एक बार निष्पादित किया जाएगा। वोइला!

UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;

SELECT * FROM x.tbl;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. JDBC org.postgresql.Driver लोड करते हुए कक्षा नहीं मिली

  2. यदि PostgreSQL के लिए मौजूद नहीं है तो डेटाबेस बनाएं सिमुलेट करें?

  3. Amazon AWS पर PostgreSQL बैकअप स्टोर करने के लिए टिप्स

  4. जब मैं एक कुंजी द्वारा एकत्रित करता हूं तो मैं निर्भर कॉलम को 'ग्रुप बाय' से बाहर क्यों नहीं कर सकता?

  5. प्रतिबद्ध पढ़ें पोस्टग्रेज़-संगत वितरित SQL डेटाबेस के लिए आवश्यक है