2012-09-10 11 views

उत्तर

18

जबकि आप के रूप में सन्नाटा समझाया पूर्णांक तक enum डाली नहीं कर सकते, तो आप एक क्रमसूचक प्रतिनिधित्व प्राप्त करने के लिए उपयोग कर सकते हैं PostgreSQL विशेष और संभवतः नहीं-संस्करण-टू-संस्करण संगत pg_enum प्रणाली सूची तालिका।

regress=# CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic'); 

regress=# select enumsortorder, enumlabel from pg_catalog.pg_enum 
regress-# WHERE enumtypid = 'happiness'::regtype ORDER BY enumsortorder; 
enumsortorder | enumlabel 
---------------+------------ 
      1 | happy 
      2 | very happy 
      3 | ecstatic 
(3 rows) 

यह आसान लग रहा है, लेकिन ऐसा नहीं है। का निरीक्षण करें:

regress=# ALTER TYPE happiness ADD VALUE 'sad' BEFORE 'happy'; 
regress=# ALTER TYPE happiness ADD VALUE 'miserable' BEFORE 'very happy'; 
regress=# SELECT * FROM pg_enum ; 
enumtypid | enumsortorder | enumlabel 
-----------+---------------+------------ 
    185300 |    1 | happy 
    185300 |    2 | very happy 
    185300 |    3 | ecstatic 
    185300 |    0 | sad 
    185300 |   1.5 | miserable 
(5 rows) 

इस से आप देख सकते हैं कि enumsortorder आदेश प्रदान करता है, लेकिन कोई निश्चित 'दूरी'। अगर enums से मूल्यों को हटाने के लिए समर्थन कभी जोड़ा जाता है, तो यह भी अनुक्रम में 'छेद' बना देगा।

enum स्थिति में आप row_number() खिड़की समारोह का उपयोग करने के आदेश प्राप्त करने के लिए की आवश्यकता होगी पाने के लिए, और pg_typeofoid enum प्रकार के (regtype) प्राप्त करने के लिए। आपको यह सुनिश्चित करने के लिए इसकी आवश्यकता है कि एक ही लेबल के साथ कई enums होने पर आप सही ordinal वापस कर दें।

इस समारोह काम करता है:

CREATE OR REPLACE FUNCTION enum_to_position(anyenum) RETURNS integer AS $$ 
SELECT enumpos::integer FROM (
     SELECT row_number() OVER (order by enumsortorder) AS enumpos, 
       enumsortorder, 
       enumlabel 
     FROM pg_catalog.pg_enum 
     WHERE enumtypid = pg_typeof($1) 
    ) enum_ordering 
    WHERE enumlabel = ($1::text); 
$$ LANGUAGE 'SQL' STABLE STRICT; 

नोट:

  • यह STABLE नहीं IMMUTABLE, क्योंकि जोड़ने (या यदि पृष्ठ में समर्थन बाद में जोड़ा जाता है, को हटाने) enums से मूल्यों को बदल जाएगा ऑर्डरिंग पर निर्भर सूचकांक को ऑर्डर करना और तोड़ना; तो
  • आप इसे इंडेक्स अभिव्यक्ति में उपयोग नहीं कर सकते हैं; और
  • यह है क्योंकि यह एक अशक्त इनपुट

अब आप integer के लिए विशिष्ट enums के लिए CREATE CAST को इस सुविधा का उपयोग कर सकते हैं के लिए अशक्त लौट जाना STRICT है। आप integer पर सभी enums के लिए एक सामान्य कास्ट नहीं बना सकते हैं, क्योंकि anyenum छद्म प्रकार का उपयोग कास्ट के लिए नहीं किया जा सकता है। उदाहरण के लिए, अगर मैं डेमो happiness पूर्णांक तक डाली जा करने के लिए अनुमति देना चाहते हैं, मैं लिखने होगा:

CREATE CAST (happiness AS integer) WITH FUNCTION enum_to_position(anyenum); 

जिसके बाद मैं सफलतापूर्वक निष्पादित कर सकते हैं:

regress=# SELECT ('happy'::happiness)::integer; 
int4 
------ 
    2 
(1 row) 

ध्यान दें कि यह शायद एक पागल है करने के लिए चीज, असमर्थित है, और काफी संभावना है कि यह एक भयानक विचार है। आपका कोड अवगत होना चाहिए कि जब आप जोड़ते हैं या (यदि बाद में समर्थित है) enum से मान हटाते हैं तो क्रमिक मान बदल जाएगा।

इस कास्ट के आधार पर बनाए गए इंडेक्स (केवल तभी संभव है जब फ़ंक्शन को अपरिवर्तनीय परिभाषित किया गया हो) पागल और गलत परिणाम उत्पन्न करना शुरू कर देगा यदि आप enum की परिभाषा को बदलते हैं (इसके अलावा नए मानों को इसके अंत में जोड़कर) क्योंकि PostgreSQL का मानना ​​है जब आप कहते हैं कि एक समारोह अपरिवर्तनीय है। ऐसा मत करो।

3

से आप पूर्णांक में एक enum कास्ट नहीं कर सकते हैं।

एक मूल्य से जुड़े नंबर को निकालने के लिए custom operator लिखने में सक्षम हो सकता है, लेकिन मुझे विश्वास करना मुश्किल लगता है कि यह समस्या के लायक है।

यदि मुझे उस तरह की जानकारी की आवश्यकता है, तो मैंने एक टेबल बनाया होगा और एक enum का उपयोग करने के बजाय इसके लिए एक विदेशी कुंजी संदर्भ सेट किया होगा।

11

आप इसे enum_range() फ़ंक्शन के चतुर दुर्व्यवहार के माध्यम से कर सकते हैं।

यदि आप enum_range() फ़ंक्शन के दूसरे तर्क के रूप में अपना enum मान पास करते हैं, तो NULL पहले होने के साथ, आपको उस बिंदु तक ले जाने वाले सभी मानों के साथ एक सरणी मिल जाएगी। फिर आपको उन्हें array_length के साथ गिनने की आवश्यकता है और आपको एक पूर्णांक मिलता है जो enum का प्रतिनिधित्व करता है।

यहां एक उदाहरण है। यह मेरी enum है:

content=# select enum_range(null::content_state); 
         enum_range       
-------------------------------------------------------------- 
{created,deleted,preview,draft,submitted,approved,published} 

और यह मुझे "ड्राफ़्ट" मूल्य के लिए पूर्णांक पता लगाना है:

content=# select array_length(enum_range(NULL, 'draft'::content_state), 1); 
array_length 
-------------- 
      4 

चेतावनी: को हटाने enum से मूल्यों अन्य मूल्यों के लिए अपने ints बिंदु कर देगा, तो इस पर उन एनमम्स पर इसका उपयोग न करें जिन्हें आप किसी बिंदु पर बदलना चाहते हैं।

0

हाँ आप कर सकते हैं।

यदि आपके एनम प्रकार में केवल पूर्णांक मान होता है तो कास्टिंग बहुत आसान हो जाता है। Create type monthenum as enum ('7', '8', '9', '10', '11', '12', '1', '2', '3', '4', '5', '6');

अब आप इस प्रकार enum मूल्यों डाली उपयोग कर सकते हैं पूर्णांक और उन्हें अलग रिकॉर्ड के रूप में प्रदर्शित करने के लिए: - -: मैं एक enum प्रकार के रूप में है मान लीजिए

select (unnest(enum_range(null::monthenum))::text)::integer as monthvalue 

आशा इस मदद करता है, विचार यह है कि आप enum को टेक्स्ट में परिवर्तित कर सकते हैं और फिर फिर अपने enum value के किसी अन्य संगत प्रकार में परिवर्तित कर सकते हैं। आप मूल्यों को एक-एक करके परिवर्तित करने के लिए लूप के लिए भी उपयोग कर सकते हैं।

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