2009-11-16 4 views
17

मुझे लगता है कि यह एक बहुत ही आम समस्या है।postgresql में पंक्तियों की अधिकतम संख्या से संबंधित बाधा कैसे लिखें?

मुझे एक टेबल user(id INT ...) और एक तालिका photo(id BIGINT, owner INT) मिली है। मालिक user(id) पर एक संदर्भ है।

मैं तालिका फ़ोटो में एक बाधा जोड़ना चाहता हूं जो 10 उपयोगकर्ताओं को प्रत्येक उपयोगकर्ता के लिए डेटाबेस में प्रवेश करने के लिए कहने से अधिक रोक देगा।

इसे लिखने का सबसे अच्छा तरीका क्या है?

Thx!

उत्तर

18

क्वास्नोई सही है; एक ट्रिगर यह हासिल करने का सबसे अच्छा तरीका होगा।

CREATE OR REPLACE FUNCTION enforce_photo_count() RETURNS trigger AS $$ 
DECLARE 
    max_photo_count INTEGER := 10; 
    photo_count INTEGER := 0; 
    must_check BOOLEAN := false; 
BEGIN 
    IF TG_OP = 'INSERT' THEN 
     must_check := true; 
    END IF; 

    IF TG_OP = 'UPDATE' THEN 
     IF (NEW.owner != OLD.owner) THEN 
      must_check := true; 
     END IF; 
    END IF; 

    IF must_check THEN 
     -- prevent concurrent inserts from multiple transactions 
     LOCK TABLE photos IN EXCLUSIVE MODE; 

     SELECT INTO photo_count COUNT(*) 
     FROM photos 
     WHERE owner = NEW.owner; 

     IF photo_count >= max_photo_count THEN 
      RAISE EXCEPTION 'Cannot insert more than % photos for each user.', max_photo_count; 
     END IF; 
    END IF; 

    RETURN NEW; 
END; 
$$ LANGUAGE plpgsql; 


CREATE TRIGGER enforce_photo_count 
    BEFORE INSERT OR UPDATE ON photos 
    FOR EACH ROW EXECUTE PROCEDURE enforce_photo_count(); 

मैं मेज शामिल आदेश स्थितियों में, जहां दो समवर्ती tansactions एक उपयोगकर्ता के लिए फ़ोटो में गिना जाएगा से बचने के लिए, देखना है कि मौजूदा संख्या सीमा से नीचे 1 है, में ताला लगा और फिर दोनों डालने:

कोड यह , जो आपको सीमा से 1 पर जाने का कारण बनता है। यदि यह आपके लिए चिंता नहीं है तो लॉकिंग को हटाना सबसे अच्छा होगा क्योंकि यह कई आवेषण/अपडेट के साथ बाधा बन सकता है।

+0

एक और बात: दुर्भाग्यवश, ट्रिगर की शुरुआत में सभी IF स्टेटमेंट्स को "IF TG_OP = 'INSERT' या (TG_OP = 'UPDATE' और NEW.owner! = OLD.owner) में शामिल नहीं किया जा सकता है फिर THEN ... "क्योंकि पीएलपीजीएसक्यूएल शॉर्ट सर्किटिंग का समर्थन नहीं करता है। –

7

आप तालिका घोषणा में ऐसी बाधा नहीं लिख सकते हैं। ,

  • एक ट्रिगर है कि प्रत्येक प्रयोक्ता
  • एक स्तंभ फ़ोटो का क्रम रखना होगा बनाएं के लिए फ़ोटो की संख्या की जाँच करेगा बनाएं (user_id, photo_order)UNIQUE बनाने के लिए, और CHECK(photo_order BETWEEN 1 AND 10) जोड़ें:

    कुछ समाधान कर रहे हैं

+1

क्या आपको फोटो आदेश पर विशिष्टता लागू नहीं करना पड़ेगा? उसको कैसे करे? – ahnbizcad

2

एक और दृष्टिकोण उपयोगकर्ता तालिका में कॉलम "photo_count" जोड़ना होगा, इसे वास्तविकता को प्रतिबिंबित करने के लिए ट्रिगर्स के साथ अपडेट करें, और अधिकतम फ़ोटो को लागू करने के लिए इसे चेक करें।

इससे साइड लाभ यह है कि किसी भी क्षण में हम जानते हैं (गिनने के बिना) उपयोगकर्ता की कितनी तस्वीरें हैं।

दूसरी तरफ - दृष्टिकोण Quassnoi सुझाव भी बहुत अच्छा है, क्योंकि यह आपको उपयोगकर्ता चाहें तो फ़ोटो को पुन: व्यवस्थित करने की क्षमता देता है।

संबंधित मुद्दे