2011-10-02 15 views
32
में मौजूद रहने पर

कहो मैं डीबी में कुछ उपयोगकर्ता-निर्धारित प्रकार बनाया है,चेक उपयोगकर्ता-निर्धारित प्रकार पहले से ही PostgreSQL

यानी CREATE TYPE abc ...

यह तो तय करें कि उपयोगकर्ता परिभाषित प्रकार मौजूद है संभव है या नहीं? शायद, पोस्टग्रेस सूचना तालिका में से किसी एक का उपयोग कर?

इसका मुख्य कारण यह है कि PostgreSQL CREATE OR REPLACE TYPE ... का समर्थन नहीं करता है, और यदि एक निश्चित प्रकार एक से अधिक बार बनाया जाता है, तो मैं पहले मौजूदा को छोड़ने में सक्षम होना चाहता हूं, फिर नया लोड कर सकता हूं।

+0

आप जानते हैं कि यदि आप अभी भी किसी तालिका द्वारा उपयोग किए जाते हैं तो आप किसी प्रकार को छोड़ या प्रतिस्थापित नहीं कर सकते हैं? –

+3

यदि आप एक प्रकार के लेनदेन में ईआरआरओआर से बचना चाहते हैं, जिसे आपने पहले से ही असफल लेनदेन के पिछले प्रयास में बनाया है, तो आप सृजन वक्तव्य से पहले हमेशा डीआरपी टाइप कर सकते हैं। – Campa

उत्तर

12

आप pg_type तालिका में देख सकते हैं:

select exists (select 1 from pg_type where typname = 'abc'); 

अगर वह सच है तो abc मौजूद है।

1

मैं एक ही काम करने की कोशिश कर रहा हूं, सुनिश्चित करें कि एक प्रकार मौजूद है।

मैं --echo-hidden (-E) के विकल्प के साथ psql शुरू कर दिया और \dT दर्ज किया गया:

$ psql -E 
psql (9.1.9) 
testdb=> \dT 
********* QUERY ********** 
SELECT n.nspname as "Schema", 
    pg_catalog.format_type(t.oid, NULL) AS "Name", 
    pg_catalog.obj_description(t.oid, 'pg_type') as "Description" 
FROM pg_catalog.pg_type t 
    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace 
WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) 
    AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) 
     AND n.nspname <> 'pg_catalog' 
     AND n.nspname <> 'information_schema' 
    AND pg_catalog.pg_type_is_visible(t.oid) 
ORDER BY 1, 2; 
************************** 
List of data types 
Schema |  Name  | Description 
--------+------------------+------------- 
public | errmsg_agg_state | 
(1 row) 

आप स्कीमा और search_path (मैं कर रहा हूँ) का उपयोग कर रहे हैं तो आप शायद pg_catalog.pg_type_is_visible(t.oid) नियंत्रण रखने के लिए की आवश्यकता होगी। मुझे नहीं पता कि कहां कर रहे हैं, लेकिन वे मेरे मामले के लिए प्रासंगिक नहीं लग रहे थे। वर्तमान में उपयोग:

SELECT 1 FROM pg_catalog.pg_type as t 
    WHERE typname = 'mytype' AND pg_catalog.pg_type_is_visible(t.oid); 
3
-- All of this to create a type if it does not exist 
CREATE OR REPLACE FUNCTION create_abc_type() RETURNS integer AS $$ 
DECLARE v_exists INTEGER; 

BEGIN 
    SELECT into v_exists (SELECT 1 FROM pg_type WHERE typname = 'abc'); 
    IF v_exists IS NULL THEN 
     CREATE TYPE abc AS ENUM ('height', 'weight', 'distance'); 
    END IF; 
    RETURN v_exists; 
END; 
$$ LANGUAGE plpgsql; 

-- Call the function you just created 
SELECT create_abc_type(); 

-- Remove the function you just created 
DROP function create_abc_type(); 
----------------------------------- 
49

मैं यहाँ एक सरल लिपि में टाइप बनाने के लिए पूर्ण समाधान जोड़ने के लिए, बस इस उद्देश्य के लिए एक समारोह बनाने की आवश्यकता के बिना।

--create types 
DO $$ 
BEGIN 
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'my_type') THEN 
     CREATE TYPE my_type AS 
     (
      --my fields here... 
     ); 
    END IF; 
    --more types here... 
END$$; 
+7

यह स्वीकार्य उत्तर होना चाहिए। –

+0

स्कीमा का उपयोग करते समय यह बिल्कुल सही नहीं है, इस तथ्य के रूप में कि pg_type तालिका में एक प्रकार मौजूद है, इसका मतलब यह नहीं है कि यह वर्तमान खोज पथ में किसी भी स्कीमा में मौजूद है। आईएसटीएम कि आपको टाइपनामस्पेस पर भी चयन करना होगा, लेकिन मुझे यकीन नहीं है कि अभी तक कैसे। – rog

+0

@rog मेरा [उत्तर] देखें (https://stackoverflow.com/a/48356064/2024692)। – Cromax

1

दरअसल, Postgres प्रकार के लिए CREATE OR REPLACE सुविधा उपलब्ध नहीं है। तो सबसे अच्छा तरीका इसे छोड़ करने के लिए है:

DROP TYPE IF EXISTS YOUR_TYPE; 
CREATE TYPE YOUR_TYPE AS (
    id  integer, 
    field varchar 
); 

सरल समाधान हमेशा सर्वश्रेष्ठ में से एक है।

+2

क्या होगा यदि वर्तमान में उस तालिका का उपयोग किसी तालिका द्वारा किया जाता है? –

+0

@ शेन फिर 'डीआरओपी' एक त्रुटि फेंक देगा। आप उपयोग कर सकते हैं, हालांकि 'ड्रॉप ... कैस्केड' भी निर्भर वस्तुओं को छोड़ने के लिए-अगर उस विशेष मामले में डेटा खोना स्वीकार्य है। – Cromax

0

@ ब्लूश के उत्तर में @ rog की दुविधा को हल करने के लिए regtype डेटा प्रकार का उपयोग करने के लिए यह अधिक उपयुक्त हो सकता है। इस पर विचार करें:

DO $$ BEGIN 
    PERFORM 'my_schema.my_type'::regtype; 
EXCEPTION 
    WHEN undefined_object THEN 
     CREATE TYPE my_schema.my_type AS (/* fields go here */); 
END $$; 

PERFORM खंड SELECT की तरह है, लेकिन यह परिणामों को छोड़ देता है, तो मूल रूप से अगर यह 'my_schema.my_type' कास्ट करने के लिए संभव है हम जाँच कर रहे हैं करने के लिए (या बस 'my_type' अगर आप स्कीमा विशिष्ट होना परवाह नहीं है) वास्तविक पंजीकृत प्रकार। यदि प्रकार मौजूद है, तो कुछ भी "गलत" नहीं होगा और RETURN पूरे ब्लॉक के अंत में कोई परिवर्तन नहीं होगा, क्योंकि my_type टाइप पहले से ही है। लेकिन अगर कास्ट संभव नहीं है, तो त्रुटि कोड 42704 फेंक दिया जाएगा जिसमें undefined_object का लेबल है। तो अगली पंक्तियों में हम उस त्रुटि को पकड़ने का प्रयास करते हैं और यदि ऐसा होता है, तो हम बस अपना नया डेटा प्रकार बनाते हैं।हम सिर्फ बनाएं प्रकार बयान एक में लपेट -

DO $$ BEGIN 
    CREATE TYPE my_type AS (/* fields go here */); 
EXCEPTION 
    WHEN duplicate_object THEN null; 
END $$; 

बस क्या तुम सच में उम्मीद कर सकते हैं:

0

आसान समाधान मैं अब तक पाया है कि स्कीमा, @ Cromax के जवाब से प्रेरित के साथ copes, यह है अपवाद हैंडलर इसलिए यह वर्तमान लेनदेन को रद्द नहीं करता है।

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