2015-06-11 10 views
5

मैं PostgreSQL तालिकाPostgreSQL अनूठा मूल्य

id ColA ColB 
------------------ 
1  'a'  'b' 
2  'c'  'd' 

मैं अद्वितीय होना कोला और ColB में मानों बनाना चाहते दोनों स्तंभ इन आवेषण के किसी भी यानी भर में मना किया जाएगा:

INSERT INTO table (ColA,ColB) values('a','e'); 
INSERT INTO table (ColA,ColB) values('z','a'); 
INSERT INTO table (ColA,ColB) values('d','g'); 

और इन आवेषण के किसी भी अनुमति दी जाएगी:

INSERT INTO table (ColA,ColB) values('z','e'); 
INSERT INTO table (ColA,ColB) values('l','k'); 

तो

CONSTRAINT unique_name UNIQUE (ColA,ColB) 

उपयुक्त नहीं है, क्योंकि यह पिछले 4 प्रविष्टियों में से किसी एक को अनुमति देगा।

उत्तर

2

अफसोस की बात है, इसे आसानी से सरल अनोखे विरोधाभास/इंडेक्स (अगर इसे हल किया जा सकता है) के साथ आसानी से हल नहीं किया जा सकता है।

आप क्या जरूरत है, एक exclusionconstraint है: टक्कर की तरह कुछ के आधार पर कुछ पंक्तियों को बाहर करने की क्षमता है,। अद्वितीय बाधाएं केवल विशिष्ट बहिष्करण बाधाएं हैं (वे समानता टकराव पर आधारित हैं)। ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]

यह सूचकांक काम कर सकता है (वर्तमान में केवल gist अनुक्रमित समर्थन:

तो, सिद्धांत रूप में, तुम बस हर row1, जहां पहले से ही एक row2, जिसके लिए यह अभिव्यक्ति सत्य है है बाहर करने की आवश्यकता बहिष्कार की कमी):

ALTER TABLE table_name 
    ADD CONSTRAINT table_name_exclusion 
    EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&); 

लेकिन दुर्भाग्य से, वहाँ सरणियों के लिए कोई डिफ़ॉल्ट ऑपरेटर वर्ग (जो gist का उपयोग करता है)। एक intarray module है, जो केवल integer सरणी के लिए एक प्रदान करता है, लेकिन text सरणी के लिए कुछ भी नहीं है।

आप वास्तव में इस बाहर काम करना चाहते हैं, तो आप हमेशा range types (f.ex. मैं आसन्न -|- ऑपरेटर, जो सभी मामलों, जो unique साथ संभाला नहीं जा सकता संभालती प्रयोग किया जाता) का दुरुपयोग कर सकते हैं ...

-- there is no built-in type for text ranges neither, 
-- but it can can be created fairly easily: 
CREATE TYPE textrange AS RANGE (
    SUBTYPE = text 
); 

ALTER TABLE table_name 
    ADD CONSTRAINT table_name_exclusion 
    EXCLUDE USING gist ((textrange(least(cola, colb), greatest(cola, colb))) WITH -|-); 

-- the exclusion constraint above does not handle all situations: 

ALTER TABLE table_name 
    ADD CONSTRAINT table_name_check 
    CHECK (cola is distinct from colb); -- without this, empty ranges could be created, 
             -- which are not adjacent to any other range 

CREATE UNIQUE INDEX table_name_unique 
    ON table_name ((ARRAY[least(cola, colb), greatest(cola, colb)])); 
    -- without this, duplicated rows could be created, 
    -- because ranges are not adjacent to themselves 

... लेकिन मुझे डर है, आपकी मूल समस्या को थोड़ा डेटाबेस रिफैक्टरिंग के साथ हल किया जा सकता है; जो हमें प्रश्न पर लाता है: क्या समस्या है, क्या आप इसके साथ हल करना चाहते हैं?