2011-07-23 20 views
31

क्या पोस्टग्रेज़ के पास ALTER TABLE foo ADD CONSTRAINT bar ... कहने का कोई तरीका है जो बाधा पहले से मौजूद है, तो यह आदेश को अनदेखा कर देगा, ताकि यह कोई त्रुटि न उठाए?पोस्टग्रेज़: यदि यह पहले से मौजूद नहीं है तो

उत्तर

18

यह मदद कर सकता है, हालांकि यह एक गंदा हैक का एक सा हो सकता है: तो फिर

create or replace function create_constraint_if_not_exists (
    t_name text, c_name text, constraint_sql text 
) 
returns void AS 
$$ 
begin 
    -- Look for our constraint 
    if not exists (select constraint_name 
        from information_schema.constraint_column_usage 
        where table_name = t_name and constraint_name = c_name) then 
     execute constraint_sql; 
    end if; 
end; 
$$ language 'plpgsql' 

फोन के साथ:

SELECT create_constraint_if_not_exists(
     'foo', 
     'bar', 
     'ALTER TABLE foo ADD CONSTRAINT bar CHECK (foobies < 100);') 

अपडेट किया गया:

प्रति Webmut's answer के रूप में सुझाव नीचे:

ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar; 
ALTER TABLE foo ADD CONSTRAINT bar ...; 

कि अपने विकास डेटाबेस में शायद ठीक है, या जहाँ आप जानते हैं आपको लगता है कि एक रखरखाव खिड़की के लिए इस डेटाबेस पर निर्भर क्षुधा को बंद कर सकते हैं।

लेकिन यदि यह एक जीवंत मिशन महत्वपूर्ण 24x7 उत्पादन वातावरण है, तो आप वास्तव में इस तरह की बाधाओं को छोड़ना नहीं चाहते हैं। यहां तक ​​कि कुछ मिलीसेकंड्स के लिए एक छोटी सी खिड़की है जहां आप अब अपनी बाधा को लागू नहीं कर रहे हैं जो ग़लत मूल्यों को फिसलने की अनुमति दे सकता है। उसमें अनपेक्षित परिणाम हो सकते हैं जिससे सड़क पर कुछ बिंदु पर काफी व्यावसायिक लागत आती है।

+0

मुझे लगता है कि आपके पिछले उदाहरण में 'myconstraint' ''bar' होना चाहिए। –

+0

@denis - अच्छी तरह पकड़ा गया। धन्यवाद। – Kev

+0

मैं इस उत्तर को और संशोधित कर दूंगा ताकि निष्पादन कथन 'निष्पादित करें' वैकल्पिक तालिका '|| t_name || 'कंसस्ट्रेंट जोड़ें' || c_name || '' || constraint_sql; 'और फ़ंक्शन को कॉल करना' SELECT create_constraint_if_not_exists ('foo', 'bar', 'चेक (foobies <100);') जैसा दिखता है; '। यह सुनिश्चित करता है कि आप अपनी बाधा एसक्यूएल में तर्कों को गड़बड़ नहीं कर सकते क्योंकि वे मूल पैरामीटर पर आधारित हैं। –

9

आप बाधा को खोजने के लिए pg_constraint मेज पर क्वेरी चला सकते हैं मौजूद है या not.like:

SELECT 1 FROM pg_constraint WHERE conname = 'constraint_name'" 
+3

वहाँ है 'ड्रॉप कन्स्ट्रेंट 'के लिए' अगर एक्सस्टिस्ट्स 'विकल्प, लेकिन, AFAIK,' कंसस्ट्रेंट जोड़ें 'के लिए कुछ नहीं। –

+0

बाध्यता नाम एक टेबल के लिए स्थानीय हैं? क्या होता है यदि 'constraint_name' नामक बाधा वाले दो तालिकाओं हैं? – guettli

+0

हां, यदि किसी अन्य तालिका में एक ही बाधा नाम था तो आप झूठी सकारात्मक प्राप्त कर सकते हैं। लेकिन यह अभी भी एक सभ्य समाधान है यदि आप अपने नामकरण के नियंत्रण में 100% हैं। –

-1

पता नहीं क्यों कोड की इतनी सारी लाइनें?

- चयन करें "कॉलम 1", "कॉलम 2", "कॉलम 3", डीबीओ से गिनती (स्टार)। "माईटेबल" ग्रुप "कॉलम 1", "कॉलम 2", "कॉलम 3" हैविंग गिनती (*)> 1;

तालिका डीबीओ को बदलें। "MyTonstraint_Name" मौजूद है "MyTable" ड्रॉप बाधा;

वैकल्पिक तालिका डीबीओ। "मायटेबल" कंसस्ट्रेंट "MyConstraint_Name" अद्वितीय ("कॉलम 1", "कॉलम 3", "कॉलम 2") जोड़ें;

33

एक संभावित समाधान केवल नई बाधा बनाने से पहले ड्रॉप IF EXISTS का उपयोग करना है।

ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar; 
ALTER TABLE foo ADD CONSTRAINT bar ...; 

INFORMATION_SCHEMA या कैटलॉग क्वेरी करने के लिए कोशिश कर रहा है की तुलना में आसान लगता है, लेकिन बहुत बड़ा टेबल पर धीमी गति से हो सकता है क्योंकि यह हमेशा बाधा का पुनर्निर्माण करने वाला।

संपादित करें 2015-07-13: केवी ने his answer में बताया कि मेरा समाधान एक छोटी सी खिड़की बनाता है जब बाधा मौजूद नहीं होती है और इसे लागू नहीं किया जा रहा है। हालांकि यह सच है, आप एक लेनदेन में दोनों बयानों को लपेटकर आसानी से ऐसी खिड़की से बच सकते हैं।

11

डुप्लिकेट ऑब्जेक्ट त्रुटि को पकड़ने के लिए आप अज्ञात डीओ ब्लॉक के अंदर अपवाद हैंडलर का उपयोग कर सकते हैं।

DO $$ 
BEGIN 

    BEGIN 
    ALTER TABLE foo ADD CONSTRAINT bar ... ; 
    EXCEPTION 
    WHEN duplicate_object THEN RAISE NOTICE 'Table constraint foo.bar already exists'; 
    END; 

END $$; 

http://www.postgresql.org/docs/9.4/static/sql-do.htmlhttp://www.postgresql.org/docs/9.4/static/plpgsql-control-structures.html http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html

+2

को 'duplicate_object' को' duplicate_table' (कोड 42P07) में बदलना था। पोस्टग्रेस 9.6 – volvpavl

0

बनाना कमी तो मैं गिर नहीं करने की सलाह देते कमी केवल तुरंत उन्हें फिर से बनाने के लिए डेटा के बहुत सारे युक्त एक मेज पर एक महंगी आपरेशन किया जा सकता है के तुरंत बाद - आप केवल कि बनाना चाहते हैं एक बार बात

मैं एक गुमनाम कोड ब्लॉक, बहुत माइक Stankavich के लिए इसी तरह का उपयोग कर इस को हल करने के लिए चुना है, लेकिन माइक (जो एक त्रुटि पकड़ता) मैं पहली बार अगर बाधा मौजूद है देखने के लिए जाँच के विपरीत:

DO $$ BEGIN IF NOT EXISTS (SELECT constraint_schema , constraint_name FROM information_schema.check_constraints WHERE constraint_schema = 'myschema' AND constraint_name = 'myconstraintname' ) THEN ALTER TABLE myschema.mytable ADD CONSTRAINT myconstraintname CHECK (column <= 100); END IF; END$$;

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