2016-04-11 10 views
5

के लिए लागू 1: 1 हमारे उत्पाद में एक कोर मॉड्यूल और कई वैकल्पिक प्लगइन्स हैं।PostgreSQL: वैकल्पिक प्लगइन

कोर में ticket_type नामक एक डेटाबेस तालिका है।

एक वैकल्पिक प्लगइन 1: 1 संबंध के माध्यम से टिकट_ प्रकार तालिका को बढ़ाता है। इस तालिका को myplugin_ticket_type_extension कहा जाता है।

myplugin_ticket_type_extension में प्रत्येक पंक्ति के लिए ticket_type में एक पंक्ति है। यह एक विदेशी के माध्यम से लागू हो जाता है। अब तक समस्याओं के लिए :-)

अब कठिन हिस्सा: ticket_type में प्रत्येक पंक्ति के लिए myplugin_ticket_type_extension में कोई पंक्ति कैसे लागू करें?

कठिन हिस्सा: myplugin एक वैकल्पिक प्लगइन है। उत्पाद के मूल को इस प्लगइन के बारे में कुछ भी नहीं पता होना चाहिए।

+0

एक्सटेंशन तालिका का संदर्भ देने वाले 'टिकट_ प्रकार 'पर विदेशी कुंजी बाधा जोड़ने से आपको क्या रोक रहा है? –

+0

@ निकबर्नेस अच्छा सवाल। तालिका 'टिकट_ प्रकार' कोर से आता है। चूंकि 'myplugin' वैकल्पिक है, प्रारंभिक तालिका में यह FK-constraint नहीं होना चाहिए। लेकिन मैं इसे प्लगइन विशिष्ट स्कीमा माइग्रेशन में जोड़ सकता हूं। – guettli

उत्तर

3

इसे लागू करने का सबसे आसान तरीका ticket_type पर दूसरी विदेशी कुंजी जोड़ना होगा जो एक्सटेंशन तालिका का संदर्भ देता है।

इस परिपत्र निर्भरता के साथ कठिनाई यह है कि किसी भी तालिका में INSERT अन्य रिकॉर्ड बनाने का मौका मिलने से पहले, किसी भी तालिका में एक विदेशी कुंजी बाधा का उल्लंघन करेगा। आप आस्थगित की कमी का उपयोग करके इस से बच सकते हैं, जो विदेशी कुंजी की जांच में विलंब होगा जब तक लेन-देन करता है:

CREATE TABLE ticket_type (id INT PRIMARY KEY); 
CREATE TABLE myplugin_ticket_type_extension (extension_field INT) INHERITS (ticket_type); 

INSERT INTO myplugin_ticket_type_extension (id, extension_field) VALUES (1,1); 

रिकॉर्ड्स डाला:

CREATE TABLE ticket_type (id INT PRIMARY KEY); 

CREATE TABLE myplugin_ticket_type_extension (
    id INT PRIMARY KEY, 
    ticket_type_id INT UNIQUE NOT NULL FOREIGN KEY 
    REFERENCES ticket_type (id) 
    DEFERRABLE INITIALLY DEFERRED 
); 
ALTER TABLE ticket_type ADD FOREIGN KEY (id) 
    REFERENCES myplugin_ticket_type_extension (ticket_type_id) 
    DEFERRABLE INITIALLY DEFERRED; 

BEGIN; 
INSERT INTO ticket_type VALUES (1); 
INSERT INTO myplugin_ticket_type_extension VALUES (1,1); 
COMMIT; 

एक वैकल्पिक दृष्टिकोण जो विचार लायक हो सकता है का उपयोग करने के table inheritance है जब आप ticket_type पर क्वेरी करते हैं तो एक्सटेंशन तालिका में दिखाया जाएगा, इसलिए आपका मूल मॉड्यूल अप्रभावित होना चाहिए।

CREATE FUNCTION ticket_type_trg() RETURNS TRIGGER AS $$ 
BEGIN 
    INSERT INTO myplugin_ticket_type_extension (id) VALUES (new.id); 
    RETURN NULL; 
END 
$$ 
LANGUAGE plpgsql; 

CREATE TRIGGER ticket_type_trg 
    BEFORE INSERT ON ticket_type FOR EACH ROW 
    EXECUTE PROCEDURE ticket_type_trg(); 
2

+1 deferrable पर: आप एक ट्रिगर, जो या तो ब्लॉक आवेषण पूरी तरह (एक अपवाद को ऊपर उठाने के द्वारा), या स्वचालित रूप से नए रिकॉर्ड विस्तार मेज पर पुन: निर्देशित कर सकती जोड़कर ticket_type तालिका में सीधे आवेषण रोका जा सकता है बाधा। उस उत्तर से एक चीज गायब है और यह है कि आप पोस्टग्रेएसक्यूएल को चेक चलाने के लिए SET CONSTRAINTS IMMEDIATE चला सकते हैं ताकि प्रतिबद्धता की प्रतीक्षा की जा सके। यह आमतौर पर डिबगिंग आदि के लिए बेहतर होता है यदि आपका एप्लिकेशन जानता है कि बाधाएं हैं।

BEGIN; 
INSERT INTO ticket_type VALUES (1); 
INSERT INTO myplugin_ticket_type_extension VALUES (1,1); 
SET CONSTRAINTS ALL IMMEDIATE; 
-- Do other work here, knowing that the above foreign key is 
-- already enforced 
COMMIT; 

ध्यान दें कि ऊपर के उदाहरण यदि आप कई आस्थगित की कमी है आप एक समस्या देता है:

उस मामले में, आपके प्रश्नों की तरह लग रहे। उन मामलों में आप इसे नाम से करना चाहते हैं (SET CONSTRAINTS name1, name2 IMMEDIATE)

+0

हां, आप सही हैं। मैंने दूसरे जवाब के लिए बक्षीस दिया क्योंकि वह तेज़ था। मुझे उम्मीद है कि यह आपके लिए सही है। – guettli

+0

ठीक है, मैंने चीजों को उस उत्तर के पूरक के रूप में भी लिखा है, इसलिए यह पता चला कि यह अधिक उपयुक्त है कि वह इसे प्राप्त करता है :-) –

0

मेरा दृष्टिकोण myplugin_ticket_type_extension होगा इसे नियंत्रित करने के लिए ticket_type तालिका में ट्रिगर्स डालने, अपडेट करने और हटाने के लिए। फिर आप इन परिचालनों पर बढ़िया नियंत्रण करेंगे और निश्चित रूप से इसकी गारंटी दे सकते हैं।

चूंकि यह एक प्रकार की तालिका है और इस प्रकार की सारणी सामान्य रूप से बहुत बड़ी नहीं होती हैं, आप सभी रिकॉर्ड्स के अनुरूप संवाददाताओं को आश्वस्त करने के लिए एक पूर्ण टेबल स्कैन भी कर सकते हैं और तदनुसार तालिका भर सकते हैं।

एक और दृष्टिकोण इस पूर्ण तालिका स्कैन और एक उचित पल में आवेदन द्वारा बुलाए गए फ़ंक्शन में अपडेट करेगा।