एक समाधान यह है कि संघर्षों का पता लगाने के लिए उपयोग करने के लिए दूसरी तालिका हो, और इसे ट्रिगर के साथ पॉप्युलेट करें। प्रश्न में जोड़े गए स्कीमा का उपयोग करना:
CREATE TABLE medicinal_product_date_map(
aic_code char(9) NOT NULL,
applicable_date date NOT NULL,
UNIQUE(aic_code, applicable_date));
(ध्यान दें:आपकी आवश्यकता को पहली बार गलत तरीके से पढ़ने के कारण यह दूसरा प्रयास है। आशा है कि यह इस बार सही है)।
इस तालिका को बनाए रखने के लिए कुछ कार्य:
CREATE FUNCTION add_medicinal_product_date_range(aic_code_in char(9), start_date date, end_date date)
RETURNS void STRICT VOLATILE LANGUAGE sql AS $$
INSERT INTO medicinal_product_date_map
SELECT $1, $2 + offset
FROM generate_series(0, $3 - $2)
$$;
CREATE FUNCTION clr_medicinal_product_date_range(aic_code_in char(9), start_date date, end_date date)
RETURNS void STRICT VOLATILE LANGUAGE sql AS $$
DELETE FROM medicinal_product_date_map
WHERE aic_code = $1 AND applicable_date BETWEEN $2 AND $3
$$;
और तालिका को पहली बार इसके साथ पॉप्युलेट करें:
SELECT count(add_medicinal_product_date_range(aic_code, vs, ve))
FROM medicinal_products;
अब मेडिसिनल_प्रोडक्ट्स में बदलाव के बाद डेट मैप को पॉप्युलेट करने के लिए ट्रिगर्स बनाएं:कॉल डालने के बाद add_, अपडेट कॉल के बाद clr_ (पुराने मान) और add_ (नए मान), डिलीट कॉल clr_ के बाद।
CREATE FUNCTION sync_medicinal_product_date_map()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
IF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN
PERFORM clr_medicinal_product_date_range(OLD.aic_code, OLD.vs, OLD.ve);
END IF;
IF TG_OP = 'UPDATE' OR TG_OP = 'INSERT' THEN
PERFORM add_medicinal_product_date_range(NEW.aic_code, NEW.vs, NEW.ve);
END IF;
RETURN NULL;
END;
$$;
CREATE TRIGGER sync_date_map
AFTER INSERT OR UPDATE OR DELETE ON medicinal_products
FOR EACH ROW EXECUTE PROCEDURE sync_medicinal_product_date_map();
मेडिसिनल_प्रोडक्ट_डेट_मैप पर अद्वितीयता बाधा किसी भी उत्पाद को उसी दिन उसी कोड के साथ जोड़े जाने से रोकेगी:
[email protected]@[local] =# INSERT INTO medicinal_products VALUES ('1','A','2010-01-01','2010-04-01');
INSERT 0 1
[email protected]@[local] =# INSERT INTO medicinal_products VALUES ('1','A','2010-03-01','2010-06-01');
ERROR: duplicate key value violates unique constraint "medicinal_product_date_map_aic_code_applicable_date_key"
DETAIL: Key (aic_code, applicable_date)=(1 , 2010-03-01) already exists.
CONTEXT: SQL function "add_medicinal_product_date_range" statement 1
SQL statement "SELECT add_medicinal_product_date_range(NEW.aic_code, NEW.vs, NEW.ve)"
PL/pgSQL function "sync_medicinal_product_date_map" line 6 at PERFORM
यह असतत स्थान रखने के लिए जाँचे जा रहे मूल्यों पर निर्भर करता है- यही कारण है कि मैंने दिनांक बनाम टाइमस्टैम्प के बारे में पूछा। हालांकि टाइमस्टैम्प, तकनीकी रूप से, असतत हैं क्योंकि Postgresql केवल माइक्रोसेकंड-रिज़ॉल्यूशन को संग्रहीत करता है, प्रत्येक माइक्रोसेकंड के लिए मानचित्र तालिका में एक प्रविष्टि जोड़ना जिसके लिए उत्पाद लागू है, व्यावहारिक नहीं है।
ऐसा कहने के बाद, आप शायद एक पूर्ण-तालिका स्कैन से बेहतर कुछ भी प्राप्त कर सकते हैं ताकि ओवरलैपिंग टाइमस्टैम्प अंतराल की जांच की जा सके, कुछ चालबाजी के साथ केवल पहले अंतराल की तलाश में पहले या पहले नहीं ... हालांकि, आसान असतत रिक्त स्थान के लिए मैं इस दृष्टिकोण को पसंद करता हूं जो आईएमई अन्य चीजों के लिए भी आसान हो सकता है (उदाहरण के लिए रिपोर्ट जो किसी निश्चित दिन पर लागू होने वाले उत्पादों को तुरंत ढूंढने की आवश्यकता होती है)।
मुझे यह दृष्टिकोण भी पसंद है क्योंकि इस तरह डेटाबेस की विशिष्टता-बाधा तंत्र का लाभ उठाना सही लगता है। साथ ही, मुझे लगता है कि यह मास्टर टेबल के समवर्ती अद्यतनों के संदर्भ में अधिक विश्वसनीय होगा:समवर्ती अद्यतनों के विरुद्ध तालिका को लॉक किए बिना, सत्यापन ट्रिगर के लिए कोई संघर्ष नहीं देखना और दो समवर्ती सत्रों में सम्मिलन की अनुमति देना संभव होगा, जो हैं तब विरोध के रूप में देखा जाता है जब दोनों लेन-देन के प्रभाव दिखाई देते हैं।