धर्मी मार्ग
आप सामान्यीकरण . पर पुनर्विचार करना चाह सकते हैं आपकी स्कीमा। हर किसी के लिए यह आवश्यक नहीं है कि "सबसे सरल प्रश्न के लिए भी शामिल हों" . एक VIEW
बनाएं उसके लिए।
तालिका इस तरह दिख सकती है:
CREATE TABLE hostname (
hostname_id serial PRIMARY KEY
, host_id int REFERENCES host(host_id) ON UPDATE CASCADE ON DELETE CASCADE
, hostname text UNIQUE
);
सरोगेट प्राथमिक कुंजी hostname_id
वैकल्पिक है . मैं एक रखना पसंद करता हूं। आपके मामले में hostname
प्राथमिक कुंजी हो सकती है। लेकिन कई ऑपरेशन सरल, छोटे integer
. के साथ तेज़ होते हैं चाबी। तालिका से लिंक करने के लिए एक विदेशी कुंजी बाधा बनाएं host
.
इस तरह एक दृश्य बनाएं:
CREATE VIEW v_host AS
SELECT h.*
, array_agg(hn.hostname) AS hostnames
-- , string_agg(hn.hostname, ', ') AS hostnames -- text instead of array
FROM host h
JOIN hostname hn USING (host_id)
GROUP BY h.host_id; -- works in v9.1+
पृष्ठ से प्रारंभ 9.1 , प्राथमिक कुंजी GROUP BY
. में SELECT
. में उस तालिका के सभी स्तंभों को शामिल करता है सूची। संस्करण 9.1 के लिए रिलीज़ नोट:
गैर-GROUP BY
. को अनुमति दें जब प्राथमिक कुंजी GROUP BY
. में निर्दिष्ट की जाती है, तो क्वेरी लक्ष्य सूची में कॉलम खंड
प्रश्न तालिका की तरह दृश्य का उपयोग कर सकते हैं। होस्टनाम खोजना बहुत होगा इस तरह से तेज़:
SELECT *
FROM host h
JOIN hostname hn USING (host_id)
WHERE hn.hostname = 'foobar';
पोस्टग्रेज में 9.2+ एक बहु-स्तंभ अनुक्रमणिका और भी बेहतर होगी यदि आप एक केवल-अनुक्रमणिका स्कैन प्राप्त कर सकते हैं इसमें से:
CREATE INDEX hn_multi_idx ON hostname (hostname, host_id);
Postgres से प्रारंभ 9.3 , आप एक MATERIALIZED VIEW
. का उपयोग कर सकते हैं , परिस्थितियों की अनुमति। खासकर यदि आप टेबल पर लिखने से ज्यादा बार पढ़ते हैं।
द डार्क साइड (जो आपने वास्तव में पूछा था)
यदि मैं तुम्हें नेक मार्ग के बारे में नहीं समझा सकता, तो मैं अंधेरे पक्ष में भी सहायता करूंगा। मै सहज हुं। :)पी>
यहां एक डेमो दिया गया है कि होस्टनाम की विशिष्टता को कैसे लागू किया जाए। मैं एक टेबल hostname
का उपयोग करता हूं टेबल पर होस्टनाम और ट्रिगर इकट्ठा करने के लिए host
इसे अद्यतित रखने के लिए। अद्वितीय उल्लंघन अपवाद उत्पन्न करते हैं और कार्रवाई को निरस्त कर देते हैं।
CREATE TABLE host(hostnames text[]);
CREATE TABLE hostname(hostname text PRIMARY KEY); -- pk enforces uniqueness
ट्रिगर फ़ंक्शन:
CREATE OR REPLACE FUNCTION trg_host_insupdelbef()
RETURNS trigger AS
$func$
BEGIN
-- split UPDATE into DELETE & INSERT
IF TG_OP = 'UPDATE' THEN
IF OLD.hostnames IS DISTINCT FROM NEW.hostnames THEN -- keep going
ELSE RETURN NEW; -- exit, nothing to do
END IF;
END IF;
IF TG_OP IN ('DELETE', 'UPDATE') THEN
DELETE FROM hostname h
USING unnest(OLD.hostnames) d(x)
WHERE h.hostname = d.x;
IF TG_OP = 'DELETE' THEN RETURN OLD; -- exit, we are done
END IF;
END IF;
-- control only reaches here for INSERT or UPDATE (with actual changes)
INSERT INTO hostname(hostname)
SELECT h
FROM unnest(NEW.hostnames) h;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
ट्रिगर:
CREATE TRIGGER host_insupdelbef
BEFORE INSERT OR DELETE OR UPDATE OF hostnames ON host
FOR EACH ROW EXECUTE PROCEDURE trg_host_insupdelbef();
एसक्यूएल फिडल टेस्ट रन के साथ।
GIN अनुक्रमणिका . का उपयोग करें सरणी कॉलम पर host.hostnames
और सरणी ऑपरेटर इसके साथ काम करने के लिए:
- मेरी PostgreSQL सरणी अनुक्रमणिका का उपयोग क्यों नहीं हो रहा है (रेल 4)?
- जांचें कि पोस्टग्रेज एरे में दिए गए मानों में से कोई एक सरणी मौजूद है या नहीं