2016-08-14 7 views
10

मैं postgres 9.5.3 का उपयोग कर रहा है, और मैं इस तरह एक मेज है:मैं एक अद्वितीय अनुक्रमणिका का संदर्भ कैसे देता हूं जो ऑन कॉन्फ्लिक्ट में फ़ंक्शन का उपयोग करता है?

CREATE FUNCTION canonical_name(text) RETURNS text AS $$ 
    SELECT replace(lower($1), '-', '_') 
$$ LANGUAGE SQL; 

मैं एक अनूठा जोड़ दिया है: इस तरह,

CREATE TABLE packages (
    id SERIAL PRIMARY KEY, 
    name VARCHAR NOT NULL 
); 

मैं एक समारोह, canonical_name परिभाषित किया है इस तालिका में इंडेक्स जो फ़ंक्शन का उपयोग करता है:

CREATE UNIQUE INDEX index_package_name 
ON packages (canonical_name(name)); 
CREATE INDEX 
# \d+ packages 
                Table "public.packages" 
Column |  Type  |      Modifiers      | Storage | Stats target | Description 
--------+-------------------+-------------------------------------------------------+----------+--------------+------------- 
id  | integer   | not null default nextval('packages_id_seq'::regclass) | plain |    | 
name | character varying | not null            | extended |    | 
Indexes: 
    "packages_pkey" PRIMARY KEY, btree (id) 
    "index_package_name" UNIQUE, btree (canonical_name(name::text)) 

और यह अद्वितीय इंडेक्स काम कर रहा है जैसा मैं उम्मीद करता हूं; यह डुप्लिकेट की प्रविष्टि को रोकता है:

INSERT INTO packages (name) 
VALUES ('Foo-bar'); 

INSERT INTO packages (name) 
VALUES ('foo_bar'); 

ERROR: duplicate key value violates unique constraint "index_package_name" 
DETAIL: Key (canonical_name(name::text))=(foo_bar) already exists. 

मेरे समस्या यह है कि मैं एक Upsert करने के लिए इस अद्वितीय सूचकांक का उपयोग करना चाहते हैं, और मैं समझ नहीं कैसे मैं संघर्ष लक्ष्य निर्दिष्ट करने के लिए की जरूरत है। एक काम Upsert के बजाय,

where conflict_target can be one of: 

    ({ index_column_name | (index_expression) } [ COLLATE collation ] [ opclass ] [, ...]) [ WHERE index_predicate ] 
    ON CONSTRAINT constraint_name 

लेकिन मैं दिखाया गया है उत्पादन त्रुटियों की कोशिश की है कि नीचे इन बातों के सभी: The documentation मैं एक सूचकांक अभिव्यक्ति निर्दिष्ट कर सकते हैं का कहना है कि लगता है।

INSERT INTO packages (name) 
VALUES ('foo_bar') 
ON CONFLICT (canonical_name(name)) 
DO UPDATE SET name = EXCLUDED.name; 

ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification 

सूचकांक अभिव्यक्ति मिलान के रूप में \d+ यह पता चला है:

मैं सूचकांक अभिव्यक्ति मिलान के रूप में मैं यह निर्दिष्ट की कोशिश की है

INSERT INTO packages (name) 
VALUES ('foo_bar') 
ON CONFLICT (canonical_name(name::text)) 
DO UPDATE SET name = EXCLUDED.name; 


ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification 

बस स्तंभ नामकरण कि अद्वितीय सूचकांक पर है :

INSERT INTO packages (name) 
VALUES ('foo_bar') 
ON CONFLICT (name) 
DO UPDATE SET name = EXCLUDED.name; 

ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification 

इसके बजाय इंडेक्स नाम का उपयोग करना:

INSERT INTO packages (name) 
VALUES ('foo_bar') 
ON CONFLICT (index_package_name) 
DO UPDATE SET name = EXCLUDED.name; 

ERROR: column "index_package_name" does not exist 
LINE 3: ON CONFLICT (index_package_name) 

तो मैं उल्लेख करूं कि मैं इस सूचकांक का उपयोग करना चाहते हैं? या यह एक बग है?

उत्तर

8

दुर्भाग्य से आप PostgreSQL के साथ ऐसा नहीं कर सकते हैं।

आप को पता चला के रूप में, आप केवल अभिव्यक्ति के लिए एक अनूठा बाधा और नहीं एक अनूठा सूचकांक के लिए एक के लिए निर्दिष्ट कर सकते हैं। यह कुछ हद तक भ्रमित है क्योंकि हुड के तहत एक अनूठी बाधा सिर्फ एक अनूठी अनुक्रमणिका है (लेकिन इसे कार्यान्वयन विस्तार माना जाता है)।

आपके लिए मामलों को और खराब बनाने के लिए, आप एक अद्वितीय इंडेक्स पर अद्वितीय बाधा परिभाषित नहीं कर सकते हैं जिसमें – है, मुझे यकीन नहीं है कि कारण क्या है, लेकिन SQL मानक पर संदेह है।

एक तरीका यह है कि आप ऐसा कर सकते हैं एक कृत्रिम कॉलम जोड़ना होगा, “ कैनोनिकल नाम ” से ट्रिगर द्वारा भरा गया और उस कॉलम पर बाधा परिभाषित करेगा। मैं मानता हूं कि यह अच्छा नहीं है।

वैकल्पिक रूप से, आप धारावाहिक लेनदेन का उपयोग कर सकते हैं और ट्रिगर को परिभाषित कर सकते हैं जो आपकी हालत को सत्यापित करता है। लेकिन इसके लिए आपको अपने कोड में क्रमबद्ध विफलताओं को संभालने की आवश्यकता होगी, जो बोझिल है।

+0

कुछ प्रयोगों के बाद, (प्रचारित इंडेक्स और फ़ंक्शन का उपयोग करके जांच बाधाओं के साथ) मुझे लगता है कि * कृत्रिम कॉलम * एकमात्र कामकाज है। – wildplasser

+2

बीटीडब्लू, 9.5.3 के बारे में निश्चित नहीं है, लेकिन 9.5.4 पर 'ऑन कॉन्फ्लिक्ट (कैनोनिकल_नाम (नाम))' संस्करण ठीक काम करता है। X86_64-pc-linux-gnu पर पोस्टग्रेएसक्यूएल 9.5.4, जीसीसी द्वारा संकलित (उबंटू 4.8.2-19ubuntu1) 4.8.2, 64-बिट' – Abelisto

+0

@ एबेलिस्टो: डॉन: मैंने सोचा कि मैंने 9.5 # हेड पर परीक्षण करने के लिए परीक्षण किया है, लेकिन यह 9.5.2 होने का प्रयास करता है ... – wildplasser

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

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