PostgreSQL'de e-posta adreslerini saklamak için doğru veri türü ne olurdu?
Kullanabilir varchar
(veya hatta text
), ancak e-postalar için daha belirli bir veri türü olup olmadığını merak ediyorum.
PostgreSQL'de e-posta adreslerini saklamak için doğru veri türü ne olurdu?
Kullanabilir varchar
(veya hatta text
), ancak e-postalar için daha belirli bir veri türü olup olmadığını merak ediyorum.
Yanıtlar:
DOMAIN
sKullanmanın citext
(büyük / küçük harfe duyarsız) yeterli olduğunu sanmıyorum [1] . PostgreSQL kullanarak , aslında bir tür üzerinde tanımlanmış bazı kısıtlamalar olan özel bir etki alanı oluşturabiliriz . Örneğin tür üzerinde veya üzerinde bir etki alanı oluşturabiliriz .citext
text
type=email
spec kullanmaŞu anda bir e-posta adresi nedir sorusuna en doğru cevap RFC5322'de belirtilmiştir . Bu özellik delicesine karmaşık [2] , öyle ki her şey onu kıracak. HTML5 e-posta için farklı bir spec içeren ,
Bu gereksinim, aynı anda çok katı ("@" karakterinden önce), çok belirsiz ("@" karakterinden sonra) ve çok gevşek (yorum yapılmasına izin veren) e-posta adreslerinin sözdizimini tanımlayan kasıtlı bir RFC 5322 ihlalidir. , boşluk karakterleri ve alıntılanan dizeler çoğu kullanıcının bilmediği yöntemlerle burada pratik olarak kullanılmalıdır. [...] Aşağıdaki JavaScript ve Perl uyumlu normal ifade, yukarıdaki tanımın bir uygulamasıdır.
/^[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])?)*$/
İstediğiniz şey bu olabilir ve HTML5 için yeterince iyiyse, muhtemelen sizin için yeterince iyidir. Bunu doğrudan PostgreSQL'de kullanabiliriz. Ayrıca citext
burada da kullanıyorum (teknik olarak basit veya küçük harfleri çıkararak basitçe biraz regex yapabilirsiniz).
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])?)*$' );
Şimdi yapabilirsin ...
SELECT 'asdf@foobar.com'::email;
Ama değil
SELECT 'asdf@foob,,ar.com'::email;
SELECT 'asd@f@foobar.com'::email;
Çünkü ikisi de geri döndü
ERROR: value for domain email violates check constraint "email_check"
Çünkü bu da citext'e dayanıyor
SELECT 'asdf@foobar.com'::email = 'ASdf@fooBAR.com';
varsayılan olarak true değerini döndürür.
plperlu
/ KullanarakEmail::Valid
Önemli bir not olarak, bunu yapmanın çok daha karmaşık bir yöntemi vardır plperlu
. Eğer doğruluğu bu düzeyde gerekiyorsa yapmak değil istiyorum citext
. Email::Valid
etki alanı MX kaydının olup olmadığını bile kontrol edebilir (örn. Email :: Valid'deki dokümanlar)! İlk önce, plperlu ekleyin (süper kullanıcı gerektirir).
CREATE EXTENSION plperlu;
Ardından fonksiyonu yaratın, aşağıdaki gibi işaretlediğimize dikkat edin 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';
$$;
Ardından etki alanını oluşturun ,
CREATE DOMAIN validemail AS text NOT NULL
CONSTRAINT validemail_check CHECK (valid_email(VALUE));
citext
teknik olarak yanlıştır. SMTP, büyük / local-part
küçük harfe duyarlı olarak tanımlar . Ancak, yine de, bu aptallık spec bir durumdur . Kendi kimlik krizlerini içeriyor. Spesifikasyonda local-part
(önceki bölüm @
) "büyük / küçük harfe duyarlı olabilir" ... "büyük / küçük harf duyarlı olarak değerlendirilmeli" "ve yine de" posta kutusunun yerel parçalarının büyük / küçük harf duyarlılığından yararlanılması birlikte çalışabilirliği engelliyor ve cesaretini kırıyor "diyor.Bu regex'lerin hiçbiri genel e-posta adresinde veya yerel kısımda veya etki alanı adlarında uzunluk sınırlarını zorlamaz. RFC 5322, herhangi bir uzunluk sınırlaması belirtmiyor. Bunlar, gerçekten e-posta göndermek için SMTP protokolü gibi diğer protokollerdeki sınırlamalardan kaynaklanmaktadır. RFC 1035, etki alanlarının 63 karakter veya daha kısa olması gerektiğini belirtir, ancak sözdizimi belirtiminde yer almaz. Bunun nedeni, gerçek bir normal dilin bir uzunluk sınırını zorlayamaması ve aynı anda ardışık kısa çizgilere izin vermemesidir.
a-z
ve A-Z
karakter sınıflarında?
~
büyük küçük harf duyarlı olduğundan , (a) büyük / ~*
küçük harfe duyarsız kullanmak veya (b) karakter sınıfında büyük ve küçük harf kullanmak zorundasınız.
citext
'ler ~
yüzden soruyorum olduğunu, küçük harf duyarsız bana gibi görünüyor.
Her zaman CITEXT
e-posta için kullanıyorum , çünkü bir e-posta adresi (uygulamada) büyük / küçük harfe duyarsız , yani John@Example.com john@example.com ile aynı.
Ayrıca, yinelenenleri engellemek için metne kıyasla benzersiz bir dizin oluşturmak daha kolaydır:
-- 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)));
E-postaları karşılaştırmak da daha kolaydır ve hatalara daha az eğilimlidir:
SELECT * FROM address WHERE email = 'JOHN@example.com';
ile kıyaslandığında:
SELECT * FROM address WHERE lower(email) = lower('JOHN@example.com');
CITEXT
"citext" adlı standart bir uzantı modülünde tanımlanan ve aşağıdakileri yazarak kullanılabilen bir türdür :
CREATE EXTENSION citext;
PS text
ve varchar
Postgres'te neredeyse aynıdır ve text
beklediğiniz gibi kullanmanın bir cezası yoktur . Bu cevabı kontrol et: Metin ve varchar arasındaki fark
Her zaman varchar(254)
bir e-posta adresi olarak kullanıyorum , 254 karakterden uzun olamaz.
Bkz. Https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-adress
Postgresql'in e-posta adresleri için yerleşik bir türü yok, ancak bazı katkıda bulunan veri türleriyle karşılaştım.
Ayrıca, üzerine benzersiz bir anahtar eklemek istemeniz durumunda e-posta adreslerini standart hale getirmek için bir tetikleyici veya bu tür bir mantık eklemek isteyebilirsiniz.
Özellikle, domain
e-posta adresinin ( local-part
@ şeklindeki domain
kısmı büyük / küçük harfe duyarsızken local-part
küçük harfe duyarlı olarak değerlendirilmelidir. Bkz. Http://tools.ietf.org/html/rfc5321#section-2.4
Diğer bir husus, isimleri ve e-posta adreslerini formda saklamak istiyorsanız "Joe Bloggs" <joe.bloggs@hotmail.com>
, bu durumda 254 karakterden daha uzun bir dizgeye ihtiyacınız olacak ve benzersiz bir kısıtlamayı anlamlı bir şekilde kullanamayacaksınız. Bunu yapmaz ve ad ve e-posta adresini ayrı ayrı saklamanızı öneririm. Sunum katmanınızda bu formatta hoş baskı adresleri her zaman mümkündür.
@
) = 320. Belki de yanlış yorumluyorum.
Bir CONSTRAINT onay denetimi kullanmakla ilgileniyor olabilirsiniz (muhtemelen daha kolay, ancak istediğinizden daha fazlasını reddedebilir veya burada ve burada tartışılan bir FUNCTION işlevini kullanırsınız . PostgreSQL bile yerel bir IP adres tipine sahip olsa da, burada bir e-posta veri türü için pgfoundry üzerinde bir proje var, ancak bu konuda bulduğum en iyi şey bir e-posta alanı.. Etki alanı bir kontrol kısıtlamasından daha iyidir, çünkü değiştirirseniz, etki alanı tanımında yalnızca bir kez yapmanız gerekir ve tüm kontrol kısıtlamalarınızı değiştiren ebeveyn-çocuk tablolarındaki izleri takip etmemelisiniz. Etki alanları gerçekten harika - veri türleri gibi, ancak uygulanması daha kolaydır. Onları Firebird'de kullandım - Oracle'da bile yok!