PostgreSQL 8.2 में गतिशील रूप से TG_TABLE_NAME का उपयोग कैसे करें? - एसक्यूएल, postgresql, समारोह, ट्रिगर्स, plpgsql

मैं एक ट्रिगर समारोह लिखने की कोशिश कर रहा हूँPostgreSQL 8.2 जो SQL कथन उत्पन्न करने और निष्पादित करने के लिए गतिशील रूप से TG_TABLE_NAME का उपयोग करेगा। मैं PostgreSQL के बाद के संस्करणों के लिए सभी प्रकार के उदाहरण पा सकता हूं, लेकिन कुछ आवश्यकताओं के कारण मैं 8.2 पर फंस गया हूं। यहां मेरा कार्य है क्योंकि यह खड़ा है जो काम करता है, लेकिन शायद ही गतिशील है:

CREATE OR REPLACE FUNCTION cdc_TABLENAME_function() RETURNS trigger AS $cdc_function$
DECLARE
op  cdc_operation_enum;
BEGIN
op = TG_OP;

IF (TG_WHEN = "BEFORE") THEN
IF (TG_OP = "UPDATE") THEN
op = "UPDATE_BEFORE";
END IF;

INSERT INTO cdc_test VALUES (DEFAULT,DEFAULT,op,DEFAULT,DEFAULT,OLD.*);
ELSE
IF (TG_OP = "UPDATE") THEN
op = "UPDATE_AFTER";
END IF;

INSERT INTO cdc_test VALUES (DEFAULT,DEFAULT,op,DEFAULT,DEFAULT,NEW.*);
END IF;

IF (TG_OP = "DELETE") THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;
END;

जिस तरह से यह वर्तमान में लिखा गया है, मेरे पास होगाप्रत्येक तालिका के लिए एक अलग ट्रिगर समारोह लिखने के लिए। मैं अपने INSERT कथन को गतिशील रूप से बनाने के लिए TG_TABLE_NAME का उपयोग करना चाहता हूं और इसे "cdc_" से उपसर्ग कर दूंगा क्योंकि सभी तालिकाएं समान नामकरण सम्मेलन का पालन करती हैं। फिर मैं प्रत्येक टेबल कॉल के लिए केवल एक समारोह के लिए हर ट्रिगर रख सकता हूं।

उत्तर:

उत्तर № 1 के लिए 13

मैं कुछ साल पहले एक ही चीज़ की तलाश में था। उन सभी पर शासन करने के लिए एक ट्रिगर समारोह! मैंने यूजनेट सूचियों से पूछा, कोई फायदा नहीं हुआ, विभिन्न दृष्टिकोणों की कोशिश की। इस मामले पर सर्वसम्मति थी यह नहीं किया जा सका। PostgreSQL 8.3 या पुराने की कमी।

PostgreSQL के बाद से 8.4 आप बस कर सकते हैं:

EXECUTE "INSERT INTO " || TG_RELID::regclass::text || " SELECT ($1).*"
USING NEW;

पीजी 8.2 के साथ आपको एक समस्या है:

  • गतिशील रूप से कॉलम तक नहीं पहुंच सकते हैं NEW / OLD। आपको जानना चाहिए ट्रिगर फ़ंक्शन लिखने के समय कॉलम नाम।
  • NEW / OLD अंदर दिखाई नहीं दे रहे हैं EXECUTE
  • EXECUTE .. USING अभी तक पैदा नहीं हुआ

हालांकि, एक चाल है।

सिस्टम में प्रत्येक तालिका का नाम एक ही नाम के समग्र प्रकार के रूप में कार्य कर सकता है। इसलिए आप एक ऐसा फ़ंक्शन बना सकते हैं जो लेता है NEW / OLD पैरामीटर के रूप में और निष्पादित करें। आप प्रत्येक ट्रिगर ईवेंट पर उस फ़ंक्शन को गतिशील रूप से बना और नष्ट कर सकते हैं:

ट्रिगर समारोह:

CREATE OR REPLACE FUNCTION trg_cdc()
RETURNS trigger AS
$func$
DECLARE
op      text := TG_OP || "_" || TG_WHEN;
tbl     text := quote_ident(TG_TABLE_SCHEMA) || "."
|| quote_ident(TG_TABLE_NAME);
cdc_tbl text := quote_ident(TG_TABLE_SCHEMA) || "."
|| quote_ident("cdc_" || TG_TABLE_NAME);
BEGIN

EXECUTE "CREATE FUNCTION f_cdc(n " || tbl || ", op text)
RETURNS void AS $x$ BEGIN
INSERT INTO " || cdc_tbl || " SELECT op, (n).*;
END $x$ LANGUAGE plpgsql";

CASE TG_OP
WHEN "INSERT", "UPDATE" THEN
PERFORM f_cdc(NEW, op);
WHEN "DELETE" THEN
PERFORM f_cdc(OLD, op);
ELSE
RAISE EXCEPTION "Unknown TG_OP: "%". Should not occur!", TG_OP;
END CASE;

EXECUTE "DROP FUNCTION f_cdc(" || tbl || ", text)";

IF TG_OP = "DELETE" THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;

END
$func$  LANGUAGE plpgsql;

ट्रिगर:

CREATE TRIGGER cdc
BEFORE INSERT OR UPDATE OR DELETE ON my_tbl
FOR EACH ROW EXECUTE PROCEDURE trg_cdc();

तालिका के नामों को उपयोगकर्ता इनपुट की तरह माना जाना चाहिए। उपयोग quote_ident() एसक्यूएल इंजेक्शन के खिलाफ बचाव करने के लिए।

तथापि, इस तरह आप प्रत्येक एकल ट्रिगर ईवेंट के लिए फ़ंक्शन बनाते और छोड़ते हैं। काफी ऊपरी, मैं इसके लिए नहीं जाऊंगा। आपको कुछ कैटलॉग टेबल को खाली करना होगा।

मैदान का मध्य

PostgreSQL का समर्थन करता है समारोह अधिभार। इसलिए, प्रति तालिका एक समारोह एक ही आधार नाम (लेकिन विभिन्न पैरामीटर प्रकार) coexist कर सकते हैं। आप मध्यम जमीन ले सकते हैं और नाटकीय रूप से शोर को कम करके कम कर सकते हैं f_cdc(..) एक बार प्रति टेबल एक बार जब आप ट्रिगर बनाते हैं। यह प्रति टेबल एक छोटा सा कार्य है। आपको टेबल परिभाषाओं के परिवर्तनों का पालन करना होगा, लेकिन तालिकाओं को अक्सर बदलना नहीं चाहिए। हटाना CREATE तथा DROP FUNCTION एक छोटे, तेज और सुरुचिपूर्ण ट्रिगर पर पहुंचने, ट्रिगर समारोह से।

मैं खुद को पीजी 8.2 में कर सकता था। सिवाय इसके कि मैं खुद को नहीं देख सकता कुछ भी अब पीजी 8.2 में। यह है दिसम्बर 2011 में जीवन के अंत तक पहुंचे। शायद आप किसी भी तरह से अपग्रेड कर सकते हैं।


जवाब के लिए 0 № 2

मैंने कुछ साल पहले भी इसी तरह के सवाल से पूछा था।

उस प्रश्न पर एक नज़र डालें और देखें कि क्या यह आपको कोई उपयोगी विचार देता है:

पीएल / pgsql में EXECUTE का उपयोग कर एक सामान्य ट्रिगर से * नया डालना


संबंधित सवाल
सबसे लोकप्रिय