DROP FUNCTION โดยอัตโนมัติเมื่อ DROP TABLE บน POSTGRESQL 11.7

ฉันกำลังพยายามทริกเกอร์ฟังก์ชันดรอปอัตโนมัติเมื่อตารางถูกดร็อป และฉันก็ไม่รู้ว่าต้องทำอย่างไร

TL;DR: มีวิธีใดที่จะทริกเกอร์ฟังก์ชันดร็อปเมื่อตารางใดตารางหนึ่งถูกดร็อปหรือไม่ (POSTGRESQL 11.7)


คำอธิบายโดยละเอียด

ฉันจะพยายามอธิบายปัญหาของฉันโดยใช้กรณีการใช้งานที่เรียบง่ายพร้อมชื่อจำลอง

  1. ฉันมีสามตาราง: sensor1, sensor2 และ sumSensors;

  2. FUNCTION (sumdata) ถูกสร้างขึ้นเพื่อ INSERT ข้อมูลบนตาราง sumSensors ภายในฟังก์ชันนี้ ฉันจะดึงข้อมูลจากตาราง sensor1 และ sensor2 และแทรกผลรวมลงใน sumSensors ของตาราง

  3. ทริกเกอร์ถูกสร้างขึ้นสำหรับตารางเซ็นเซอร์แต่ละตัวซึ่งมีลักษณะดังนี้:

    สร้างทริกเกอร์ trig1 หลังจากใส่เซ็นเซอร์ 1 สำหรับแต่ละแถว เรียกใช้ฟังก์ชัน sumdata();

  4. ตอนนี้ เมื่อ แทรกแถวใหม่ บนโต๊ะ sensor1 หรือ sensor2 ฟังก์ชัน sumdata จะถูกดำเนินการและ แทรกผลรวมของค่าสุดท้ายจากทั้งสองบนตาราง sumSensors

หากฉันต้องการ DROP FUNTION sumdata CASCADE; ทริกเกอร์จะถูกลบออกจากตาราง sensor1 และ sensor2 โดยอัตโนมัติ จนถึงตอนนี้ทุกอย่างก็เรียบร้อยดี! แต่นั่นไม่ใช่สิ่งที่ฉันต้องการ


ปัญหาของฉันคือ:

ถาม: และถ้าฉันแค่ DROP TABLE sumSensors CASCADE;? จะเกิดอะไรขึ้นกับฟังก์ชันที่ตั้งใจจะแทรกลงในตารางนี้?

ตอบ: ตามที่คาดไว้ เนื่องจากไม่มีการเชื่อมโยงระหว่างตาราง sumSensors และฟังก์ชัน sumdata ฟังก์ชันจะไม่ถูกทิ้ง (ยังคงมีอยู่)! สิ่งเดียวกันนี้เกิดขึ้นกับทริกเกอร์ที่ใช้งาน (ยังคงมีอยู่) ซึ่งหมายความว่าเมื่อมีการแทรกแถวใหม่บนตารางเซ็นเซอร์ ข้อมูลรวมของฟังก์ชันจะถูก ดำเนินการและเสียหาย ซึ่งนำไปสู่ความล้มเหลว (แม้แต่ INSERT ที่ทริกเกอร์การทำงานของฟังก์ชันก็จะไม่ถูกแทรกจริง ๆ )

มีวิธีทริกเกอร์ฟังก์ชั่นดร็อปเมื่อตารางใดตารางหนึ่งถูกดร็อปหรือไม่?

ขอบคุณล่วงหน้า


person NelsonC    schedule 15.04.2020    source แหล่งที่มา


คำตอบ (1)


ไม่มีการติดตามการพึ่งพาสำหรับฟังก์ชันใน PostgreSQL (ตั้งแต่เวอร์ชัน 12)

คุณสามารถใช้ทริกเกอร์เหตุการณ์เพื่อรักษาการอ้างอิงได้ด้วยตัวเอง

ตัวอย่างเต็มดังต่อไปนี้

ข้อมูลเพิ่มเติม: เอกสารประกอบของคุณลักษณะทริกเกอร์เหตุการณ์, ฟังก์ชันการสนับสนุน

BEGIN;

CREATE TABLE _testtable ( id serial primary key, payload text );

INSERT INTO _testtable (payload) VALUES ('Test data');

CREATE FUNCTION _testfunc(integer) RETURNS integer
LANGUAGE SQL AS $$ SELECT $1 + count(*)::integer FROM _testtable; $$;

SELECT _testfunc(100);

CREATE FUNCTION trg_drop_dependent_functions()
RETURNS event_trigger 
LANGUAGE plpgsql AS $$
DECLARE
    _dropped record;
BEGIN
    FOR _dropped IN
        SELECT schema_name, object_name
        FROM pg_catalog.pg_event_trigger_dropped_objects()
        WHERE object_type = 'table'
    LOOP
        IF _dropped.schema_name = 'public' AND _dropped.object_name = '_testtable' THEN
            EXECUTE 'DROP FUNCTION IF EXISTS _testfunc(integer)';
        END IF;
    END LOOP;
END;
$$;

CREATE EVENT TRIGGER trg_drop_dependent_functions ON sql_drop
EXECUTE FUNCTION trg_drop_dependent_functions();

DROP TABLE _testtable;

ROLLBACK;
person filiprem    schedule 16.04.2020
comment
เยี่ยมมาก นั่นช่วยแก้ปัญหาของฉันได้ ขอบคุณมาก @filiprem จริงๆ แล้ว! - person NelsonC; 16.04.2020