यदि यह मौजूद नहीं है तो इंडेक्स बनाएं


60

मैं एक फ़ंक्शन पर काम कर रहा हूं जो मुझे एक इंडेक्स जोड़ने की अनुमति देता है अगर यह मौजूद नहीं है। मैं इस समस्या में भाग रहा हूं कि मुझे तुलना करने के लिए अनुक्रमित की सूची नहीं मिल सकती है। कोई विचार?

यह स्तंभ निर्माण के लिए एक समान मुद्दा है जो इस कोड के साथ हल किया गया है:
https://stackoverflow.com/a/12603892/368511


आप कोशिश कर सकते हैं: pg_indexes से चयन करें * जहां स्कीमनाम = '[स्कीमन]' और इंडेक्सनेम = '[इंडेक्सनेम]'। उचित मूल्यों के साथ [योजनाबद्ध] और [अनुक्रमणिका] बदलें। Ref: postgresql.org/docs/9.1/static/view-pg-indexes.html
jbarrameda

जवाबों:


102

PostgreSQL में सूचकांक नाम

  • इंडेक्स नाम एकल डेटाबेस स्कीमा में अद्वितीय हैं।
  • अनुक्रमणिका नाम किसी भी अन्य अनुक्रमणिका, (विदेशी) तालिका, (भौतिक) दृश्य, अनुक्रम या उपयोगकर्ता-परिभाषित समग्र प्रकार के समान स्कीमा में समान नहीं हो सकते।
  • एक ही स्कीमा में दो तालिकाओं में एक ही नाम का सूचकांक नहीं हो सकता है। (तार्किक रूप से अनुसरण करता है।)

यदि आपको इंडेक्स के नाम की परवाह नहीं है, तो इसे पोस्ट-ऑटो नाम दें:

CREATE INDEX ON tbl1 (col1);

(लगभग) के समान है:

CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);

सिवाय इसके कि Postgres एक नामकरण टकराव से बचेंगे और स्वचालित रूप से अगला स्वतंत्र नाम चुनेंगे:

tbl1_col1_idx 
tbl1_col1_idx2
tbl1_col1_idx3
...

कर के देखो। लेकिन, जाहिर है, आप कई निरर्थक सूचकांक नहीं बनाना चाहेंगे। तो यह सिर्फ एक आँख बंद करके एक नया बनाने के लिए एक अच्छा विचार नहीं होगा।

अस्तित्व के लिए परीक्षण करें

9.3 या पुराने पोस्टग्रेट्स

परीक्षण करने के लिए एक बहुत ही सरल तरीका है स्कीमा-योग्य नाम को regclassनिम्न पर डालना :

SELECT 'myschema.myname'::regclass;

यदि यह एक अपवाद फेंकता है, तो नाम मुफ्त है।
या, एक DOबयान में इस्तेमाल एक अपवाद फेंकने के बिना उसी का परीक्षण करने के लिए :

DO
$$
BEGIN
   IF NOT EXISTS (
      SELECT
      FROM   pg_class c
      JOIN   pg_namespace n ON n.oid = c.relnamespace
      WHERE  c.relname = 'mytable_mycolumn_idx'
      AND    n.nspname = 'myschema'
   ) THEN

        CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
    END IF;
END
$$;

यह काम नहीं करता है CREATE INDEX CONCURRENTLY, क्योंकि यह संस्करण बाहरी लेनदेन में लपेटा नहीं जा सकता है। नीचे @Gregory द्वारा टिप्पणी देखें ।

DOबयान Postgres 9.0 के साथ पेश किया गया था। पहले के संस्करणों में आपको ऐसा करने के लिए एक फ़ंक्शन बनाना होगा । मैनुअल में
विवरण । मैनुअल में इंडेक्स के बारे में मूल बातें ।pg_class

प्रेषित करता है 9.4

आप to_regclass()बिना किसी अपवाद को फेंकने के लिए नए फ़ंक्शन का उपयोग कर सकते हैं :

DO
$$
BEGIN
   IF to_regclass('myschema.mytable_mycolumn_idx') IS NULL THEN
      CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
   END IF;

END
$$;

उस नाम का कोई इंडेक्स (या अन्य ऑब्जेक्ट) मौजूद नहीं होने पर NULL लौटाता है। देख:

9.5 का पदभार

अब उपलब्ध है:

CREATE INDEX IF NOT EXISTS ...

वह भी काम करता है CREATE INDEX CONCURRENTLY IF NOT EXISTS

हालाँकि, मैनुअल चेतावनी देता है :

ध्यान दें कि इस बात की कोई गारंटी नहीं है कि मौजूदा इंडेक्स कुछ भी है जो बनाया गया है।

यह ऑब्जेक्ट नाम के लिए एक सादा चेक है। यहां सभी प्रकारों पर लागू होता है।


7
एक शानदार उत्तर होने के दौरान, ध्यान दें कि आप CONCURRENTLYइस तरह अनुक्रमित नहीं जोड़ सकते हैं । आपको मिलेगा ERROR: CREATE INDEX CONCURRENTLY cannot be executed from a function or multi-command string
gregoltsov

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.