Was wäre der richtige Datentyp, um E-Mail-Adressen in PostgreSQL zu speichern?
Ich kann varchar
(oder sogar text
) verwenden, aber ich frage mich, ob es einen spezifischeren Datentyp für E-Mails gibt.
Was wäre der richtige Datentyp, um E-Mail-Adressen in PostgreSQL zu speichern?
Ich kann varchar
(oder sogar text
) verwenden, aber ich frage mich, ob es einen spezifischeren Datentyp für E-Mails gibt.
Antworten:
DOMAIN
sIch denke nicht, dass die Verwendung von citext
(Groß- / Kleinschreibung wird nicht berücksichtigt) ausreicht [1] . Mit PostgreSQL können wir eine benutzerdefinierte Domäne erstellen, bei der es sich im Wesentlichen um einige definierte Einschränkungen für einen Typ handelt . Wir können eine Domain zum Beispiel über den citext
Typ oder über erstellen text
.
type=email
Spezifikation verwendenDie aktuell korrekteste Antwort auf die Frage, was eine E-Mail-Adresse ist, ist in RFC5322 angegeben . Diese Spezifikation ist wahnsinnig komplex [2] , so sehr, dass alles kaputt geht. HTML5 enthält eine andere Spezifikation für E-Mail ,
Diese Anforderung stellt eine vorsätzliche Verletzung von RFC 5322 dar, das eine Syntax für E-Mail-Adressen definiert, die gleichzeitig zu streng (vor dem Zeichen "@"), zu vage (nach dem Zeichen "@") und zu lasch (Kommentare zulassen) ist , Whitespace-Zeichen und Anführungszeichen in für die meisten Benutzer ungewohnter Weise), um hier von praktischem Nutzen zu sein. [...] Der folgende JavaScript- und Perl-kompatible reguläre Ausdruck ist eine Implementierung der obigen Definition.
/^[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])?)*$/
Dies ist wahrscheinlich das, was Sie wollen, und wenn es gut genug für HTML5 ist, ist es wahrscheinlich gut genug für Sie. Das können wir direkt in PostgreSQL nutzen. Ich verwende auch citext
hier (was technisch bedeutet, dass Sie die Regex einfach ein wenig visuell darstellen können, indem Sie entweder die Groß- oder Kleinschreibung entfernen).
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])?)*$' );
Jetzt können Sie tun ...
SELECT 'asdf@foobar.com'::email;
Aber nicht
SELECT 'asdf@foob,,ar.com'::email;
SELECT 'asd@f@foobar.com'::email;
Weil beide zurückkehren
ERROR: value for domain email violates check constraint "email_check"
Weil dies auch auf citext basiert
SELECT 'asdf@foobar.com'::email = 'ASdf@fooBAR.com';
gibt standardmäßig true zurück.
plperlu
/Email::Valid
Ein wichtiger Hinweis ist, dass es eine korrektere Methode gibt, die mit der Verwendung weitaus komplexer ist plperlu
. Wenn Sie diesen Grad an Korrektheit benötigen , möchten Sie nichtcitext
. Email::Valid
kann sogar überprüfen, ob die Domain einen MX-Eintrag hat (Beispiel in den Dokumenten von Email :: Valid)! Fügen Sie zunächst plperlu hinzu (Superuser erforderlich).
CREATE EXTENSION plperlu;
Dann die Funktion erstellen , bemerken wir als markieren 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';
$$;
Dann erstelle die Domain ,
CREATE DOMAIN validemail AS text NOT NULL
CONSTRAINT validemail_check CHECK (valid_email(VALUE));
citext
ist technisch falsch. SMTP unterscheidet local-part
zwischen Groß- und Kleinschreibung. Aber auch dies ist ein Fall, in dem die Spezifikation dumm ist. Es enthält seine eigenen Identitätskrisen. In der Spezifikation steht local-part
(der Teil vor dem @
) "MUSS zwischen Groß- und Kleinschreibung unterschieden werden" ... "MUSS zwischen Groß- und Kleinschreibung unterschieden werden" ... und dennoch "behindert das Ausnutzen der Groß- und Kleinschreibung lokaler Mailbox-Teile die Interoperabilität und wird davon abgeraten".Keine dieser regulären Ausdrücke erzwingt Längenbeschränkungen für die gesamte E-Mail-Adresse oder den lokalen Teil oder die Domain-Namen. RFC 5322 legt keine Längenbeschränkungen fest. Diese ergeben sich aus Einschränkungen in anderen Protokollen wie dem SMTP-Protokoll zum tatsächlichen Senden von E-Mails. RFC 1035 gibt an, dass Domänen maximal 63 Zeichen lang sein dürfen, schließt dies jedoch nicht in die Syntaxspezifikation ein. Der Grund dafür ist, dass eine echte reguläre Sprache kein Längenlimit erzwingen und gleichzeitig aufeinanderfolgende Bindestriche nicht zulassen kann.
a-z
und A-Z
in den Charakterklassen zu haben?
~
Groß- und Kleinschreibung unterschieden wird, muss entweder ~*
(a) die Groß- und Kleinschreibung nicht beachtet werden oder (b) die Groß- und Kleinschreibung in der Zeichenklasse angegeben werden.
citext
‚s ~
scheint , Groß- und Kleinschreibung zu mir zu sein, das ist , warum ich frage.
Ich verwende immer CITEXT
für E-Mails, da eine E-Mail-Adresse (in der Praxis) nicht zwischen Groß- und Kleinschreibung unterscheidet , dh John@Example.com ist identisch mit john@example.com.
Es ist auch einfacher, einen eindeutigen Index einzurichten, um Duplikate im Vergleich zu Text zu vermeiden:
-- 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)));
Das Vergleichen von E-Mails ist außerdem einfacher und weniger fehleranfällig:
SELECT * FROM address WHERE email = 'JOHN@example.com';
verglichen mit:
SELECT * FROM address WHERE lower(email) = lower('JOHN@example.com');
CITEXT
ist ein Typ, der in einem Standard-Erweiterungsmodul mit dem Namen "citext" definiert ist und durch Eingabe von:
CREATE EXTENSION citext;
PS text
und varchar
sind praktisch die gleichen in Postgres und es gibt keine Strafe für die Verwendung, text
wie man erwarten kann. Überprüfen Sie diese Antwort: Unterschied zwischen Text und Varchar
Ich benutze immer varchar(254)
als E-Mail-Adresse darf nicht länger als 254 Zeichen sein.
Siehe https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address
Postgresql hat keinen eingebauten Typ für E-Mail-Adressen, obwohl ich auf einen beitragenden Datentyp gestoßen bin.
Außerdem möchten Sie möglicherweise einen Auslöser oder eine solche Logik hinzufügen, um E-Mail-Adressen zu standardisieren, falls Sie einen eindeutigen Schlüssel hinzufügen möchten.
Insbesondere muss der domain
Teil der E-Mail-Adresse (in der Form local-part
@ zwischen domain
Groß- und Kleinschreibung unterschieden werden, während zwischen Groß- und Kleinschreibung unterschieden werden local-part
muss). Siehe http://tools.ietf.org/html/rfc5321#section-2.4
Eine weitere Überlegung ist, ob Sie Namen und E-Mail-Adressen im Formular speichern möchten. "Joe Bloggs" <joe.bloggs@hotmail.com>
In diesem Fall benötigen Sie eine Zeichenfolge mit mehr als 254 Zeichen und können keine eindeutige Einschränkung sinnvoll verwenden. Ich würde dies nicht tun und empfehlen, Name und E-Mail-Adresse getrennt zu speichern. Hübsche Druckadressen in diesem Format sind in Ihrer Präsentationsebene immer möglich.
@
).
@
) = 320. Vielleicht interpretiere ich es falsch.
Möglicherweise möchten Sie einen check CONSTRAINT verwenden (möglicherweise einfacher, aber lehnen Sie möglicherweise mehr ab, als Sie möchten, oder verwenden Sie eine hier und hier diskutierte FUNCTION. Grundsätzlich geht es um Kompromisse zwischen Spezifität und einfacher Implementierung. Interessantes Thema though. PostgreSQL hat auch einen native IP - Adresstyp, aber es ist ein Projekt auf pgfoundry für einen E - Mail - Datentyp hier . aber das beste , was ich dazu gefunden ist eine E - Mail - Domain. Die Domäne ist besser als eine Überprüfungsbedingung, da Sie sie bei einer Änderung in der Domänendefinition nur einmal ausführen müssen und nicht den Nachverfolgungen von Eltern-Kind-Tabellen folgen müssen, um alle Ihre Überprüfungsbedingungen zu ändern. Domänen sind wirklich cool - ein bisschen wie Datentypen, aber einfacher zu implementieren. Ich habe sie in Firebird verwendet - Oracle hat sie nicht einmal!