Какой тип данных подходит для хранения адресов электронной почты в PostgreSQL?
Я могу использовать varchar
(или даже text
), но мне интересно, есть ли более конкретный тип данных для электронных писем.
Какой тип данных подходит для хранения адресов электронной почты в PostgreSQL?
Я могу использовать varchar
(или даже text
), но мне интересно, есть ли более конкретный тип данных для электронных писем.
Ответы:
DOMAIN
sЯ не думаю, что использования citext
(без учета регистра) достаточно [1] . Используя PostgreSQL, мы можем создать собственный домен, который, по сути, представляет собой определенные ограничения для типа . Мы можем создать домен, например, над citext
типом или более text
.
type=email
спецификации HTML5В настоящее время наиболее правильный ответ на вопрос, что такое адрес электронной почты, указан в RFC5322 . Эта спецификация безумно сложна [2] , настолько, что все ломает ее. HTML5 содержит другую спецификацию для электронной почты ,
Это требование является преднамеренным нарушением RFC 5322, который определяет синтаксис для адресов электронной почты, который является одновременно слишком строгим (до символа "@"), слишком расплывчатым (после символа "@") и слишком слабым (допускает комментарии , пробельные символы и строки в кавычках способами, незнакомыми большинству пользователей) для практического использования здесь. [...] Следующее JavaScript- и Perl-совместимое регулярное выражение является реализацией приведенного выше определения.
/^[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])?)*$/
Это, вероятно, то, что вы хотите, и если он достаточно хорош для HTML5, то, вероятно, достаточно хорош для вас Мы можем использовать это непосредственно в 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';
возвращает true по умолчанию.
plperlu
/Email::Valid
Важным примечанием является то, что существует более правильный метод, который гораздо сложнее использовать plperlu
. Если вам нужен этот уровень корректности, вы не хотите citext
. Email::Valid
Можно даже проверить, есть ли в домене запись MX (например, в документах Email :: Valid)! Сначала добавьте plperlu (требуется суперпользователь).
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));
citext
технически неправильно. SMTP определяется local-part
как чувствительный к регистру. Но, опять же, это тот случай, когда спецификация глупа. Это содержит свои собственные кризисы идентичности. Спецификация говорит local-part
(часть перед@
) «МОЖЕТ быть чувствительной к регистру» ... «ДОЛЖНА БЫТЬ рассматриваться как чувствительная к регистру» ... и все же «использование чувствительности к регистру локальных частей почтового ящика препятствует взаимодействию и не рекомендуется».Ни одно из этих регулярных выражений не налагает ограничений на длину общего адреса электронной почты, локальной части или доменных имен. RFC 5322 не устанавливает ограничений по длине. Они проистекают из ограничений других протоколов, таких как протокол SMTP для фактической отправки электронной почты. RFC 1035 заявляет, что домены должны содержать не более 63 символов, но не включает их в свою спецификацию синтаксиса. Причина в том, что настоящий регулярный язык не может одновременно устанавливать ограничение длины и запрещать последовательные дефисы.
a-z
и другое A-Z
в классах персонажей?
~
учетом регистра вы должны (а) использовать ~*
регистр без учета регистра или (б) иметь буквы верхнего и нижнего регистра в классе char.
citext
«s , ~
кажется, нечувствительны к регистру для меня, поэтому я спрашиваю.
Я всегда использую 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;
PS text
и varchar
в Postgres они практически одинаковы, и штраф за использование, text
как и следовало ожидать, отсутствует. Проверьте этот ответ: Разница между текстом и varchar
Я всегда использую 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 символов, и вы не сможете осмысленно использовать уникальное ограничение. Я бы не стал делать это и предлагал бы хранить имя и адрес электронной почты отдельно. Красивая печать адресов в этом формате всегда возможна на вашем уровне представления.
@
).
@
) = 320. Возможно, я неверно истолковываю это.
Возможно, вам будет интересно использовать проверку CONSTRAINT (возможно, проще, но вы можете отклонить больше, чем вы хотели бы, или вы используете FUNCTION, обсуждаемые здесь и здесь . По сути, все дело в компромиссе между спецификой и простотой реализации. Интересная тема хотя. PostgreSQL даже имеет нативную IP тип адреса, но есть проект по pgfoundry для типа данных по электронной почте здесь . Тем не менее, лучшее , что я нашел про это письмо домен, Домен лучше, чем проверочное ограничение, потому что если вы измените его, вам нужно будет сделать это только один раз в определении домена, а не следовать следам таблиц типа «родители-потомки», изменяя все ваши проверочные ограничения. Домены действительно крутые - вроде как типы данных, но проще в реализации. Я использовал их в Firebird - у Oracle их даже нет!