एक संभावित समाधान एक माध्यमिक तालिका बनाना है जो आपकी चाबियों के उपसर्ग रखता है, और उसके बाद विशिष्टता और बहिष्कार बाधाओं के संयोजन का उपयोग करें जो आपके इच्छित विशिष्टता अर्थशास्त्र को लागू करने के लिए एक सम्मिलित ट्रिगर के साथ होता है।
एक उच्च स्तर पर, इस दृष्टिकोण उपसर्गों की एक सूची में नीचे प्रत्येक कुंजी टूट जाता है और पाठकों-लेखक ताला शब्दों के कुछ इसी तरह लागू होता है: कुंजी के किसी भी संख्या कुंजियों में से कोई भी रूप के रूप में लंबे समय से एक उपसर्ग साझा कर सकते हैं के बराबर होती है उपसर्ग। इसे पूरा करने के लिए, उपसर्गों की सूची में एक ध्वज के साथ कुंजी शामिल है जो इसे टर्मिनल उपसर्ग के रूप में चिह्नित करती है।
द्वितीयक तालिका इस तरह दिखती है। हम ध्वज के लिए BOOLEAN
की बजाय CHAR
का उपयोग करते हैं क्योंकि बाद में हम एक बाधा जोड़ देंगे जो बूलियन कॉलम पर काम नहीं करता है।
CREATE TABLE prefixes (
id INTEGER NOT NULL,
prefix TEXT NOT NULL,
is_terminal CHAR NOT NULL,
CONSTRAINT prefixes_id_fk
FOREIGN KEY (id)
REFERENCES your_table (id)
ON DELETE CASCADE,
CONSTRAINT prefixes_is_terminal
CHECK (is_terminal IN ('t', 'f'))
);
अब हम भी prefixes
में पंक्तियों को सम्मिलित करने के your_table
में डालने पर एक ट्रिगर निर्धारित करने होंगे ऐसी है कि
INSERT INTO your_table (id, key) VALUES (1, ‘abc');
का कारण बनता है
INSERT INTO prefixes (id, prefix, is_terminal) VALUES (1, 'a', ‘f’);
INSERT INTO prefixes (id, prefix, is_terminal) VALUES (1, 'ab', ‘f’);
INSERT INTO prefixes (id, prefix, is_terminal) VALUES (1, 'abc', ’t’);
ट्रिगर समारोह कैसा लग सकता है इस। मैं केवल INSERT
मामले को कवर कर रहा हूं, लेकिन UPDATE
को संभालने के साथ-साथ पुराने उपसर्गों को हटाकर और फिर नए डालने के लिए फ़ंक्शन को बनाया जा सकता है। DELETE
केस prefixes
पर कैस्केडिंग विदेशी-कुंजी बाधा से ढका हुआ है।
CREATE OR REPLACE FUNCTION insert_prefixes() RETURNS TRIGGER AS $$
DECLARE
is_terminal CHAR := 't';
remaining_text TEXT := NEW.key;
BEGIN
LOOP
IF LENGTH(remaining_text) <= 0 THEN
EXIT;
END IF;
INSERT INTO prefixes (id, prefix, is_terminal)
VALUES (NEW.id, remaining_text, is_terminal);
is_terminal := 'f';
remaining_text := LEFT(remaining_text, -1);
END LOOP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
हम इस फ़ंक्शन को सामान्य रूप से ट्रिगर के रूप में तालिका में जोड़ते हैं।
CREATE TRIGGER insert_prefixes
AFTER INSERT ON your_table
FOR EACH ROW
EXECUTE PROCEDURE insert_prefixes();
एक बहिष्करण बाधा और एक आंशिक अद्वितीय सूचकांक एक पंक्ति जहां is_terminal = ’t’
अपने is_terminal
मूल्य की परवाह किए बिना एक ही उपसर्ग की एक और पंक्ति के साथ टकराते नहीं कर सकते हैं, और वहाँ is_terminal = ’t’
साथ केवल एक पंक्ति है कि कि लागू करेंगे:
ALTER TABLE prefixes ADD CONSTRAINT prefixes_forbid_conflicts
EXCLUDE USING gist (prefix WITH =, is_terminal WITH <>);
CREATE UNIQUE INDEX ON prefixes (prefix) WHERE is_terminal = 't';
यह नई पंक्तियों को अनुमति देता है जो संघर्ष नहीं करते हैं लेकिन मल्टी-पंक्ति INSERT सहित संघर्ष करने वाले लोगों को रोकते हैं।
db=# INSERT INTO your_table (id, key) VALUES (1, 'a.b.c');
INSERT 0 1
db=# INSERT INTO your_table (id, key) VALUES (2, 'a.b.b');
INSERT 0 1
db=# INSERT INTO your_table (id, key) VALUES (3, 'a.b');
ERROR: conflicting key value violates exclusion constraint "prefixes_forbid_conflicts"
db=# INSERT INTO your_table (id, key) VALUES (4, 'a.b.c');
ERROR: duplicate key value violates unique constraint "prefixes_prefix_idx"
db=# INSERT INTO your_table (id, key) VALUES (5, 'a.b.c.d');
ERROR: conflicting key value violates exclusion constraint "prefixes_forbid_conflicts"
db=# INSERT INTO your_table (id, key) VALUES (6, 'a.b.d'), (7, 'a');
ERROR: conflicting key value violates exclusion constraint "prefixes_forbid_conflicts"
मैं इस तरह से जा रहा था, तो मैंने कंपनी पोस्टग्रेस को बहुत पुराना पाया, 'एक्स्क्लुड' बाधाओं का समर्थन नहीं करता! जो फ़ंक्शन आप चाहते हैं वह स्थिति ($ 2 में $ 1)> 0 या स्थिति ($ 1 में $ 2)> 0. –
तालिका में कई रिकॉर्ड हो सकते हैं। क्या यह दृष्टिकोण किसी भी सूचकांक का उपयोग कर सकता है? –
@ जुराज हां, इस एक्सक्लुड फीचर को हमेशा एक इंडेक्स की आवश्यकता होती है, इसलिए बाधा तेजी से होती है। बीटीडब्ल्यू - समाधान अब पूरा हो गया है तो कृपया इसका परीक्षण करें (9.1+ पर काम करना चाहिए) – filiprem