PostgreSQL में एक ईमेल पते को स्टोर करने का सबसे अच्छा तरीका क्या है?


40

PostgreSQL में ईमेल पतों को संग्रहीत करने के लिए सही डेटाटाइप क्या होगा?

मैं varchar(या यहां तक ​​कि text) का उपयोग कर सकता हूं , लेकिन मुझे आश्चर्य है कि क्या ईमेल के लिए अधिक विशिष्ट डेटा प्रकार है।

जवाबों:


38

कस्टम DOMAINएस

मुझे नहीं लगता कि citextकेस (असंवेदनशील) का उपयोग करना पर्याप्त है [1] । PostgreSQL का उपयोग करके हम एक कस्टम डोमेन बना सकते हैं जो अनिवार्य रूप से एक प्रकार से कुछ परिभाषित बाधाएं हैं । हम उदाहरण के लिए citext, या ओवर के लिए एक डोमेन बना सकते हैं text

HTML5 type=emailकल्पना का उपयोग करना

वर्तमान में प्रश्न का सबसे सही उत्तर ई-मेल पता RFC5322 में निर्दिष्ट है । यह कल्पना पागलपन से जटिल है [2] , इतना सब कुछ इसे तोड़ देता है। HTML5 में ईमेल के लिए एक अलग युक्ति है ,

यह आवश्यकता RFC 5322 का एक विलक्षण उल्लंघन है, जो ई-मेल पते के लिए एक वाक्यविन्यास को परिभाषित करता है जो एक साथ बहुत सख्त है ("@" चरित्र से पहले), बहुत अस्पष्ट ("@" चरित्र के बाद), और बहुत ढीला (टिप्पणी की अनुमति देता है) , व्हाट्सएप पात्र, और अधिकांश उपयोगकर्ताओं के लिए अपरिचित लोगों में उद्धृत तार) यहां व्यावहारिक उपयोग के लिए। [...] निम्नलिखित जावास्क्रिप्ट- और पर्ल-संगत नियमित अभिव्यक्ति उपरोक्त परिभाषा का कार्यान्वयन है।

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

यह संभावना है कि आप क्या चाहते हैं, और यदि यह एचटीएमएल 5 के लिए पर्याप्त है, तो संभवतः यह आपके लिए काफी अच्छा है। इसका उपयोग हम सीधे PostgreSQL में कर सकते हैं। मैं citextयहां भी उपयोग करता हूं (जो तकनीकी रूप से इसका मतलब है कि आप ऊपरी-मामले या निचले-मामले को हटाकर बस नेत्रहीन को थोड़ा सा देख सकते हैं)।

CREATE EXTENSION citext;
CREATE DOMAIN email AS citext
  CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$' );

अब आप कर सकते हैं ...

SELECT 'asdf@foobar.com'::email;

लेकिन नहीं

SELECT 'asdf@foob,,ar.com'::email;
SELECT 'asd@f@foobar.com'::email;

क्योंकि वे दोनों वापस लौट आए

ERROR:  value for domain email violates check constraint "email_check"

क्योंकि यह citext पर भी आधारित है

SELECT 'asdf@foobar.com'::email = 'ASdf@fooBAR.com';

डिफ़ॉल्ट रूप से सही है।

का उपयोग कर plperlu/Email::Valid

एक महत्वपूर्ण नोट के रूप में, ऐसा करने का एक अधिक सही तरीका है जो कि कहीं अधिक जटिल है plperlu। यदि आपको इस स्तर की शुद्धता चाहिए तो आप नहीं चाहते citextEmail::Validयह भी देख सकता है कि डोमेन में एमएक्स रिकॉर्ड है (उदाहरण के लिए डॉक्स में ईमेल :: मान्य)! सबसे पहले, प्लपरलू (सुपरयुजर की आवश्यकता है) जोड़ें।

CREATE EXTENSION plperlu;

फिर फ़ंक्शन बनाएं , ध्यान दें कि हम इस पर चिह्नित करते हैं IMMUTABLE:

CREATE FUNCTION valid_email(text)
  RETURNS boolean
  LANGUAGE plperlu
  IMMUTABLE LEAKPROOF STRICT AS
$$
  use Email::Valid;
  my $email = shift;
  Email::Valid->address($email) or die "Invalid email address: $email\n";
  return 'true';
$$;

फिर डोमेन बनाएं ,

CREATE DOMAIN validemail AS text NOT NULL
  CONSTRAINT validemail_check CHECK (valid_email(VALUE));

फुटनोट

  1. citextतकनीकी रूप से गलत का उपयोग करना । SMTP local-partकेस संवेदनशील होने के रूप में परिभाषित करता है । लेकिन, फिर से, यह कल्पना के मूर्ख होने का मामला है । इसमें अपनी अलग पहचान होती है। युक्ति कहती है local-part( @" पहले वाला मामला संवेदनशील है" ... "केस सेंसिटिव के रूप में माना जाना चाहिए ..." और फिर भी "मेलबॉक्स के मामले संवेदनशीलता का दोहन स्थानीय भागों में अंतर को बाधित करता है और इसे हतोत्साहित किया जाता है।"
  2. एक ईमेल पते के लिए कल्पना इतनी जटिल है, यह आत्म-निहित भी नहीं है। कॉम्प्लेक्स वास्तव में एक समझ है, जो कल्पना कर रहे हैं वे भी इसे नहीं समझते हैं। । डॉक्स से regular-expression.info पर

    इनमें से न तो regexes समग्र ईमेल पते या स्थानीय भाग या डोमेन नाम पर लंबाई सीमा लागू करते हैं। RFC 5322 किसी भी लंबाई सीमा को निर्दिष्ट नहीं करता है। वास्तव में ईमेल भेजने के लिए एसएमटीपी प्रोटोकॉल जैसे अन्य प्रोटोकॉल में सीमाओं से स्टेम। RFC 1035 बताता है कि डोमेन 63 वर्ण या उससे कम का होना चाहिए, लेकिन इसके सिंटैक्स विनिर्देश में शामिल नहीं है। कारण यह है कि एक सच्ची नियमित भाषा एक लंबाई सीमा को लागू नहीं कर सकती है और एक ही समय में लगातार हाइफ़न को अस्वीकार कर सकती है।


1
W3.org लिंक टूट गया है; यहाँ एक वैकल्पिक स्रोत है: html.spec.whatwg.org/multipage/…
MaxGabriel

@MaxGabriel धन्यवाद स्टिक के चारों ओर, आपको संपादित परमिट जल्द ही मिल जाएंगे, मैं इसे वहां तय कर दूंगा।
इवान कैरोल

वहाँ दोनों के लिए एक कारण है a-zऔर A-Zचरित्र वर्गों में?
xehpuk

@xehpuk अच्छी तरह से, क्योंकि ~मामला संवेदनशील है या तो आपको (ए) का उपयोग ~*असंवेदनशील है या (बी) चार-वर्ग में ऊपरी और निचले मामले पत्र हैं।
इवान कैरोल

citextकी ~, केस-संवेदी मेरे लिए हो रहा है कि मैं क्यों पूछ रहा हूँ।
xehpuk

46

मैं हमेशा CITEXTईमेल के लिए उपयोग करता हूं , क्योंकि एक ईमेल पता असंवेदनशील है , यानी John@Example.com john@example.com जैसा ही है।

पाठ की तुलना में डुप्लिकेट को रोकने के लिए एक अद्वितीय सूचकांक सेटअप करना भी आसान है:

-- citext
CREATE TABLE address (
   id serial primary key,
   email citext UNIQUE,
   other_stuff json
);

-- text
CREATE TABLE address (
   id serial primary key,
   email text,
   other_stuff json
);
CREATE UNIQUE INDEX ON address ((lower(email)));

ईमेल की तुलना करना भी आसान है और त्रुटियों की संभावना कम है:

SELECT * FROM address WHERE email = 'JOHN@example.com';

इसकी तुलना में:

SELECT * FROM address WHERE lower(email) = lower('JOHN@example.com');

CITEXTएक प्रकार है जिसे "citext" नाम के मानक विस्तार मॉड्यूल में परिभाषित किया गया है , और टाइप करके उपलब्ध है:

CREATE EXTENSION citext;

पी एस textऔर varcharवस्तुतः पोस्टग्रेज में समान हैं और textउम्मीद के मुताबिक उपयोग करने के लिए कोई जुर्माना नहीं है। इस उत्तर की जाँच करें: पाठ और varchar के बीच अंतर


10

मैं हमेशा varchar(254)एक ईमेल पते के रूप में उपयोग करता हूं जो 254 वर्णों से अधिक लंबा नहीं हो सकता है।

Https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address देखें

Postgresql के पास ईमेल पतों के लिए कोई अंतर्निहित प्रकार नहीं है, हालांकि मैं कुछ योगदान डेटा प्रकारों में आया था।

इसके अलावा, यदि आप इस पर एक अनूठी कुंजी जोड़ना चाहते हैं, तो आप ईमेल पतों को मानकीकृत करने के लिए एक ट्रिगर या कुछ ऐसे तर्क जोड़ना चाह सकते हैं।

विशेष रूप से, domainईमेल पता (फार्म की है, जिनमें से हिस्सा local-part@ domainकेस संवेदी है, जबकि local-partकेस संवेदी के रूप में व्यवहार किया जाना चाहिए। देखें http://tools.ietf.org/html/rfc5321#section-2.4

एक अन्य विचार यह है कि यदि आप प्रपत्र में नाम और ईमेल पते संग्रहीत करना चाहते हैं "Joe Bloggs" <joe.bloggs@hotmail.com>, तो इस स्थिति में आपको 254 वर्णों से अधिक लंबे तार की आवश्यकता होती है और आप सार्थक रूप से एक अद्वितीय बाधा का उपयोग करने में सक्षम नहीं होंगे। मैं ऐसा नहीं करूंगा और नाम और ईमेल पते को अलग से संग्रहीत करने का सुझाव दूंगा। इस प्रारूप में सुंदर मुद्रण पते आपकी प्रस्तुति परत में हमेशा संभव है।


4.5.3.1 के अनुसार आकार सीमा और न्यूनतम , अधिकतम लंबाई 320 वर्ण (सहित @) है।
एंड्री एम

1
@AndriyM संदर्भित खंड में कुछ भी नहीं है जो 320 कहता है। और वैसे भी यह गलत है; tools.ietf.org/html/rfc5321#section-4.5.3.3.3 बताता है कि एक पथ की अधिकतम लंबाई 256 वर्ण है, और जिसमें अधिकतम 254 बनाने के लिए आसपास "<" और ">" शामिल है।
कॉलिन 'टी हार्ट

मैं 4.5.3.1.1 ("एक उपयोगकर्ता नाम या अन्य स्थानीय-भाग की अधिकतम कुल लंबाई 64 ओकटेट") और 4.5.3.1.2 ("डोमेन नाम की अधिकतम कुल लंबाई के आधार पर अधिकतम 320 के रूप में आया था" या संख्या 255 ओकटेट है ")। तो, 64 + 255 + 1 ( @ए) = 320. शायद मैं इसे गलत समझ रहा हूं।
एंड्री एम

3
@AndriyM मेरे द्वारा जुड़े प्रश्न के स्वीकृत उत्तर को पढ़ें। यह सब समझाता है। यह निश्चित रूप से 254 है, न कि 320.
कॉलिन का हार्ट हार्ट

3

आप एक जांच उपयोग करने में रुचि हो सकता है बाधा (संभवतः आसान है, लेकिन एक से अधिक आप करना चाहते हैं अस्वीकार कर सकते हैं, या आप एक समारोह पर चर्चा की का उपयोग यहाँ और यहाँ । Bascially, यह विशिष्टता के बीच तालमेल के बारे में सब है और कार्यान्वयन में आसानी। दिलचस्प विषय हालाँकि, PostgreSQL में एक मूल IP पता प्रकार भी होता है, लेकिन यहाँ एक ईमेल डेटा प्रकार के लिए pgfoundry पर एक परियोजना है । हालाँकि, इस बारे में मुझे जो सबसे अच्छा मिला वह एक ईमेल डोमेन है।। डोमेन एक चेक बाधा से बेहतर है क्योंकि यदि आप इसे बदलते हैं, तो आपको इसे केवल डोमेन परिभाषा में एक बार करना होगा और अपने सभी चेक बाधाओं को बदलते हुए पैरेंट-चाइल्ड टेबल नीचे ट्रेल्स का पालन नहीं करना होगा। डोमेन वास्तव में शांत हैं - डेटा प्रकार की तरह थोड़े, लेकिन लागू करने के लिए सरल। मैं उन्हें Firebird में इस्तेमाल किया - Oracle भी उन्हें नहीं है!

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