PostgreSQL में अहस्ताक्षरित पूर्णांक उपलब्ध क्यों नहीं है?


113

मैं इस पोस्ट पर आया ( MySQL में छोटे, छोटे, मध्यम, बिगिन और int के बीच अंतर क्या है? ) और महसूस किया कि PostgreSQL अहस्ताक्षरित पूर्णांक का समर्थन नहीं करता है।

क्या कोई यह समझाने में मदद कर सकता है कि ऐसा क्यों है?

ज्यादातर समय, मैं अहस्ताक्षरित पूर्णांक का उपयोग MySQL में स्वतः वृद्धि प्राथमिक कुंजी के रूप में करता हूं। ऐसे डिज़ाइन में, जब मैं MySQL से PostgreSQL में अपना डेटाबेस पोर्ट करता हूं, तो मैं इसे कैसे पार कर सकता हूं?

धन्यवाद।


अभी तक नहीं लेकिन जल्द ही और हम PostgreSQL में जाने पर विचार कर रहे हैं।
एड्रियन हो डे

4
मुझे नहीं लगता कि यह पूछने के लिए सबसे अच्छी जगह है कि कुछ निर्णय क्यों किए गए थे, पोस्टग्रेक्यूएल मेलिंग सूचियों में से एक अधिक उपयुक्त हो सकता है। यदि आप ऑटो-इन्क्रिमेंटिंग मान चाहते हैं तो serial(1 से 2147483647) या bigserial(1 से 9223372036854775807) का उपयोग करें। एक हस्ताक्षरित 64 बिट पूर्णांक संभवतः पर्याप्त कमरे से अधिक प्रदान करता है।
म्यू बहुत कम है

4
थैंक्स @ मयूइस्टोशॉर्ट। कि प्राथमिक कुंजी मुद्दे का जवाब दिया। लेकिन कैसे एक अहस्ताक्षरित पूर्णांक प्रकार के बारे में जो न तो ऑटो इंक्रीमेंट किया गया और न ही प्राथमिक कुंजी? मेरे पास ऐसे कॉलम हैं जो अहस्ताक्षरित पूर्णांक को संग्रहीत करते हैं जिसमें 0 से 2 ^ 32 तक की सीमा होती है।
एड्रियन हो डे

4
PostgreSQL डॉक्स ( postgresql.org/docs/current/interactive/index.html ) के माध्यम से एक त्वरित रन आपके लिए उपयोगी हो सकता है जिससे आपको पता चल सके कि PostgreSQL सक्षम है। इन दिनों MySQL का उपयोग करने का एकमात्र कारण यह है कि अगर मैंने पहले ही इसमें बहुत कुछ निवेश कर लिया था: PostgreSQL तेजी से, उपयोगी सुविधाओं से भरी हुई है, और उन लोगों द्वारा निर्मित है जो अपने डेटा के बारे में बहुत पागल हैं। IMO का कोर्स :)
म्यू बहुत कम है

संकेत के लिए फिर से @muistooshort धन्यवाद।
एड्रियन हो डे

जवाबों:


47

यह पहले से ही उत्तर दिया गया है कि क्यों postgresql में अहस्ताक्षरित प्रकार का अभाव है। हालांकि मैं अहस्ताक्षरित प्रकारों के लिए डोमेन का उपयोग करने का सुझाव दूंगा।

http://www.postgresql.org/docs/9.4/static/sql-createdomain.html

 CREATE DOMAIN name [ AS ] data_type
    [ COLLATE collation ]
    [ DEFAULT expression ]
    [ constraint [ ... ] ]
 where constraint is:
 [ CONSTRAINT constraint_name ]
 { NOT NULL | NULL | CHECK (expression) }

डोमेन एक प्रकार की तरह है लेकिन एक अतिरिक्त बाधा के साथ।

एक ठोस उदाहरण के लिए आप उपयोग कर सकते हैं

CREATE DOMAIN uint2 AS int4
   CHECK(VALUE >= 0 AND VALUE < 65536);

जब मैं प्रकार का दुरुपयोग करने की कोशिश करता हूं तो psql क्या देता है।

DS1 = # चयन (346346 :: uint2);

त्रुटि: डोमेन uint2 के लिए मान चेक का उल्लंघन करता है "uint2_check"


लेकिन मुझे लगता है कि इस डोमेन का उपयोग हर बार जब हम चाहते हैं कि एक अहस्ताक्षरित कॉलम INSERT / UPDATE पर ओवरहेड होगा। इसका उपयोग करने के लिए बेहतर है जहां यह वास्तव में आवश्यक है (जो कि दुर्लभ है) और सिर्फ इस विचार के लिए उपयोग किया जाता है कि डेटाटाइप कम सीमा की इच्छा नहीं रखता है। आखिरकार, यह एक ऊपरी सीमा भी रखता है जो आमतौर पर एक तार्किक दृष्टिकोण से अर्थहीन होता है। न्यूमेरिक प्रकार हमारे एप्लिकेशन बाधाओं को लागू करने के लिए डिज़ाइन नहीं हैं।
फेडेरिको रेज़ोली

इस दृष्टिकोण के साथ एकमात्र समस्या यह है कि आप 15 बिट डेटा भंडारण को "बर्बाद" कर रहे हैं जो अप्रयुक्त हैं। चेक का उल्लेख नहीं करने से दक्षता की कुछ छोटी राशि भी खर्च होती है। बेहतर समाधान होगा प्रथम श्रेणी के रूप में अहस्ताक्षरित जोड़ना पोस्टग्रैज। 20 मिलियन रिकॉर्ड के साथ एक तालिका में, इस तरह से अनुक्रमित क्षेत्र के साथ, आप अप्रयुक्त बिट्स पर 40 एमबी अंतरिक्ष बर्बाद कर रहे हैं। यदि आप गाली दे रहे हैं कि 20 अन्य तालिकाओं में, अब आप 800MB स्थान बर्बाद कर रहे हैं।
तपती

85

यह SQL मानक में नहीं है, इसलिए इसे लागू करने का सामान्य आग्रह कम है।

कई अलग-अलग पूर्णांक प्रकार होने से रिज़ॉल्यूशन सिस्टम अधिक नाजुक हो जाता है, इसलिए मिश्रण में अधिक प्रकार जोड़ने के लिए कुछ प्रतिरोध है।

उस ने कहा, कोई कारण नहीं है कि यह नहीं किया जा सकता है। यह सिर्फ बहुत काम है।


35
यह सवाल काफी लोकप्रिय है कि मैंने इसे ठीक करने के लिए निर्धारित किया है: github.com/petere/pguint
पीटर आइसेनट्राट

अहस्ताक्षरित पूर्णांक शाब्दिक के लिए इनपुट / आउटपुट रूपांतरण होने के बावजूद सुपर उपयोगी होगा। या यहां तक ​​कि सिर्फ एक to_charपैटर्न।
बरगी

37

आप एक CHECK बाधा का उपयोग कर सकते हैं, जैसे:

CREATE TABLE products (
    product_no integer,
    name text,
    price numeric CHECK (price > 0)
);

इसके अलावा, PostgreSQL है smallserial, serialऔर bigserialऑटो वेतन वृद्धि के लिए प्रकार के।


2
एक बात का उल्लेख है, आप उन स्तंभों में कोई NULLs नहीं कर सकते हैं जो CHECK का उपयोग करते हैं।
Minutis

1
@Minutis क्या आप सुनिश्चित हैं कि आपके पास x नहीं है या x 4 और 40
jgmjgm

और यह आपको वैसा ही रिज़ॉल्यूशन नहीं देता है, जैसा कि अगर यह अहस्ताक्षरित int था। मतलब अहस्ताक्षरित int तक जा सकते हैं 2^32-1, इस बीच हस्ताक्षरित ints तक जा सकते हैं 2^31-1
ज्यूकसऑन आप

2
NULLऔर CHECKपूरी तरह से ऑर्थोगोनल हैं। आप के साथ या बिना NULL/ NOT NULLकॉलम हो सकते हैं CHECK। बस ध्यान दें कि, postgresql.org/docs/9.4/ddl-constraints.html पर प्रलेखन के अनुसार , CHECKNULL TRUE का मूल्यांकन करता है, इसलिए यदि आप वास्तव में NULLs को रोकना चाहते हैं, तो NOT NULLइसके बजाय (या इसके अलावा CHECK) का उपयोग करें।
flaviovs

एक CHECK का उपयोग करने से मुझे ipv4 पतों को स्टोर करने की अनुमति नहीं मिलती है integer(बिना उनके बेतरतीब ढंग से पॉजिटिव या नेगेटिव जाने के, कम से कम ..)
hanshenrik

5

DOMAINS के बारे में बात दिलचस्प है लेकिन उस प्रश्न के एकमात्र संभावित मूल के लिए प्रासंगिक नहीं है। अहस्ताक्षरित किलों की इच्छा समान संख्या में बिट्स के साथ ints की सीमा को दोगुना करना है, यह एक दक्षता तर्क है, नकारात्मक संख्याओं को बाहर करने की इच्छा नहीं है, हर कोई जानता है कि एक चेक बाधा कैसे जोड़ना है।

जब किसी ने इसके बारे में पूछा , तो टोम लेन ने कहा:

मूल रूप से, शून्य मौका है यह तब तक होगा जब तक कि आप उन्हें संख्यात्मक पदोन्नति पदानुक्रम में फिट करने का एक तरीका नहीं पा सकते हैं जो बहुत सारे मौजूदा अनुप्रयोगों को नहीं तोड़ता है। हमने इसे एक से अधिक बार देखा है, यदि स्मृति कार्य करती है, और एक व्यावहारिक डिजाइन के साथ आने में विफल रही जो पीओएलए का उल्लंघन नहीं करती थी।

"POLA" क्या है? Google ने मुझे 10 परिणाम दिए जो कि व्यर्थ हैं । यकीन नहीं होता कि यह राजनीतिक रूप से गलत है और इसलिए सेंसर किया गया। यह खोज शब्द कोई परिणाम क्यों नहीं देगा? जो कुछ।

आप बिना अधिक परेशानी के एक्सटेंशन प्रकार के रूप में अहस्ताक्षरित इनट्स को लागू कर सकते हैं। यदि आप इसे सी-फ़ंक्शंस के साथ करते हैं, तो कोई प्रदर्शन दंड नहीं होगा। आपको शाब्दिकों से निपटने के लिए पार्सर का विस्तार करने की आवश्यकता नहीं होगी क्योंकि PgSQL में स्ट्रिंग्स को शाब्दिक रूप से व्याख्या करने का इतना आसान तरीका है, बस '4294966272' :: uint4 को अपने शाब्दिक रूप में लिखें। कास्ट एक बड़ी बात नहीं होनी चाहिए। आपको सीमा अपवाद करने की भी आवश्यकता नहीं है, आप बस '4294966273' के शब्दार्थ का इलाज कर सकते हैं :: uint4 :: int as -1024। या आप एक त्रुटि फेंक सकते हैं।

अगर मुझे ये चाहिए होता तो मैं कर देता। लेकिन जब से मैं एसक्यूएल के दूसरी तरफ जावा का उपयोग कर रहा हूं, मेरे लिए यह बहुत कम मूल्य का है क्योंकि जावा में उन अहस्ताक्षरित पूर्णांक नहीं हैं। इसलिए मुझे कुछ नहीं मिला। अगर मैं एक Bigint कॉलम से BigInteger मिलता हूं, तो मैं पहले से ही नाराज हूं, जब इसे लंबे समय तक फिट होना चाहिए।

एक और बात, अगर मुझे 32 बिट या 64 बिट प्रकारों को स्टोर करने की आवश्यकता होती है, तो मैं क्रमशः PostgreSQL int4 या int8 का उपयोग कर सकता हूं, बस यह याद रखना कि प्राकृतिक क्रम या अंकगणित मज़बूती से काम नहीं करेगा। लेकिन भंडारण और पुनर्प्राप्ति इसके द्वारा अप्रभावित है।


यहां बताया गया है कि मैं एक सरल अहस्ताक्षरित int8 को कैसे लागू कर सकता हूं:

पहले मैं उपयोग करूंगा

CREATE TYPE name (
    INPUT = uint8_in,
    OUTPUT = uint8_out
    [, RECEIVE = uint8_receive ]
    [, SEND = uint8_send ]
    [, ANALYZE = uint8_analyze ]
    , INTERNALLENGTH = 8
    , PASSEDBYVALUE ]
    , ALIGNMENT = 8
    , STORAGE = plain
    , CATEGORY = N
    , PREFERRED = false
    , DEFAULT = null
)

न्यूनतम 2 कार्य uint8_inऔर uint8_outमुझे पहले परिभाषित करना चाहिए।

CREATE FUNCTION uint8_in(cstring)
    RETURNS uint8
    AS 'uint8_funcs'
    LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION uint64_out(complex)
    RETURNS cstring
    AS 'uint8_funcs'
    LANGUAGE C IMMUTABLE STRICT;

C uint8_funcs.c में इसे लागू करने की आवश्यकता है। इसलिए मैं यहां से जटिल उदाहरण का उपयोग करता हूं और इसे सरल बनाता हूं :

PG_FUNCTION_INFO_V1(complex_in);

Datum complex_in(PG_FUNCTION_ARGS) {
    char       *str = PG_GETARG_CSTRING(0);
    uint64_t   result;

    if(sscanf(str, "%llx" , &result) != 1)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                 errmsg("invalid input syntax for uint8: \"%s\"", str)));

    return (Datum)SET_8_BYTES(result);
}

अच्छी तरह से आह, या आप बस इसे पहले से ही पा सकते हैं


1
मैं अनुमान लगा रहा हूं कि POLA "कम से कम विस्मय का सिद्धांत" है। यह बताता है कि परिवर्तन में अप्रत्याशित तरीकों से मौजूदा व्यवहार को बदलने की क्षमता है।
डॉक्टर एवल

1

नवीनतम प्रलेखन के अनुसार, एकांत पूर्णांक समर्थित है लेकिन तालिका में कोई अहस्ताक्षरित पूर्णांक नहीं है। हालांकि, धारावाहिक प्रकार एक तरह से बिना भेजे के समान है, सिवाय इसके कि यह शून्य से 1 से शुरू होता है। लेकिन ऊपरी सीमा एक जैसी है। तो प्रणाली वास्तव में अहस्ताक्षरित समर्थन नहीं है। जैसा कि पीटर ने बताया, अहस्ताक्षरित संस्करण को लागू करने के लिए दरवाजा खुला है। कोड को बहुत अपडेट करना पड़ सकता है, बस C प्रोग्रामिंग के साथ काम करने के मेरे अनुभव से बहुत अधिक काम है।

https://www.postgresql.org/docs/10/datatype-numeric.html

integer     4 bytes     typical choice for integer  -2147483648 to +2147483647
serial  4 bytes     autoincrementing integer    1 to 2147483647

0

Postgres में एक अहस्ताक्षरित पूर्णांक प्रकार होता है जो कई के लिए अनभिज्ञ होता है OID:।

oidप्रकार वर्तमान में एक अहस्ताक्षरित चार-बाइट पूर्णांक के रूप में कार्यान्वित किया जाता है। [...]

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

हालांकि यह एक संख्यात्मक प्रकार नहीं है, और इसके साथ कोई भी अंकगणित (या यहां तक ​​कि बिटवाइज़ संचालन) करने की कोशिश विफल हो रही है। इसके अलावा, यह सिर्फ 4 बाइट्स ( INTEGER) है, इसमें कोई 8 बाइट ( BIGINT) अहस्ताक्षरित प्रकार नहीं है।

तो यह वास्तव में अपने आप को उपयोग करने के लिए एक अच्छा विचार नहीं है, और मैं अन्य सभी उत्तरों से सहमत हूं कि Postgresql डेटाबेस डिज़ाइन में आपको हमेशा अपने धारावाहिक प्राथमिक कुंजी के लिए एक कॉलम INTEGERया BIGINTकॉलम का उपयोग करना चाहिए - इसे नकारात्मक में शुरू करना ( ) या इसे अनुमति देना यदि आप पूर्ण डोमेन को समाप्त करना चाहते हैं ( तो)MINVALUECYCLE

हालाँकि, इनपुट / आउटपुट रूपांतरण के लिए यह काफी उपयोगी है, जैसे कि किसी अन्य DBMS से आपका माइग्रेशन। 2147483648किसी पूर्णांक स्तंभ में मान सम्मिलित करने से "कार्य : पूर्णांक सीमा से बाहर " हो जाएगा, जबकि अभिव्यक्ति का उपयोग 2147483648::OIDठीक काम करता है।
इसी तरह, जब पूर्णांक कॉलम को पाठ के रूप में चुनते हैं mycolumn::TEXT, तो आपको कुछ बिंदु पर नकारात्मक मान मिलेगा, लेकिन आपके साथ mycolumn::OID::TEXTहमेशा एक प्राकृतिक संख्या प्राप्त होगी।

Dbfiddle.uk पर एक उदाहरण देखें ।


यदि आपको संचालन की आवश्यकता नहीं है, तो OID का उपयोग करने का एकमात्र मूल्य यह है कि आपका क्रम क्रम काम करता है। अगर वह है जो आपको चाहिए, ठीक है। लेकिन जल्द ही कोई uint8 चाहता है और फिर वे भी खो जाते हैं। लब्बोलुआब यह है कि 32 बिट या 64 बिट मूल्यों को स्टोर करने के लिए आप क्रमशः int4 और int8 का उपयोग कर सकते हैं, बस संचालन के साथ सावधान रहने की आवश्यकता है। लेकिन विस्तार से लिखना आसान है।
गनथर स्कैडो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.