Quel serait le bon type de données pour stocker les adresses électroniques dans PostgreSQL?
Je peux utiliser varchar
(ou même text
), mais je me demande s’il existe un type de données plus spécifique pour les courriels.
Quel serait le bon type de données pour stocker les adresses électroniques dans PostgreSQL?
Je peux utiliser varchar
(ou même text
), mais je me demande s’il existe un type de données plus spécifique pour les courriels.
Réponses:
DOMAIN
sJe ne pense pas que l'utilisation de citext
(insensible à la casse) soit suffisante [1] . En utilisant PostgreSQL, nous pouvons créer un domaine personnalisé qui est essentiellement constitué de contraintes définies sur un type . Nous pouvons créer un domaine par exemple sur le citext
type ou sur text
.
type=email
spécification HTML5Actuellement, la réponse la plus correcte à la question de savoir ce qu’est une adresse électronique est spécifiée dans la RFC5322 . Cette spécification est incroyablement complexe [2] , à tel point que tout le casse. HTML5 contient une spécification différente pour le courrier électronique ,
Cette exigence est une violation volontaire de la RFC 5322, qui définit une syntaxe pour les adresses électroniques simultanément à la fois trop stricte (avant le caractère "@"), trop vague (après le caractère "@") et trop laxiste (permettant des commentaires). , les caractères d’espace, et les chaînes citées de manière inconnue de la plupart des utilisateurs) sont ici utiles. [...] L'expression régulière suivante compatible JavaScript et Perl est une implémentation de la définition ci-dessus.
/^[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])?)*$/
C'est probablement ce que vous voulez, et si c'est suffisant pour HTML5, il l'est probablement pour vous. Nous pouvons l'utiliser directement dans PostgreSQL. J'utilise aussi citext
ici (ce qui signifie techniquement que vous pouvez simplement visionner légèrement l'expression régulière en supprimant les majuscules ou les minuscules).
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])?)*$' );
Maintenant tu peux faire ...
SELECT 'asdf@foobar.com'::email;
Mais non
SELECT 'asdf@foob,,ar.com'::email;
SELECT 'asd@f@foobar.com'::email;
Parce que tous les deux reviennent
ERROR: value for domain email violates check constraint "email_check"
Parce que c'est aussi basé sur le citext
SELECT 'asdf@foobar.com'::email = 'ASdf@fooBAR.com';
renvoie vrai par défaut.
plperlu
/Email::Valid
Il est important de noter qu’il existe une méthode plus correcte, beaucoup plus complexe, pour ce faire plperlu
. Si vous avez besoin de ce niveau de correction, vous ne voulez pascitext
. Email::Valid
peut même vérifier si le domaine a un enregistrement MX (exemple dans la documentation de Email :: Valid)! Premièrement, ajoutez plperlu (nécessite le superutilisateur).
CREATE EXTENSION plperlu;
Puis créez la fonction , notez que nous marquons en tant que 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';
$$;
Puis créez le domaine ,
CREATE DOMAIN validemail AS text NOT NULL
CONSTRAINT validemail_check CHECK (valid_email(VALUE));
citext
est techniquement incorrecte. SMTP définit local-part
comme étant sensible à la casse. Mais, encore une fois, c’est un cas de spécification stupide. Il contient ses propres crises d'identité. La spécification indique local-part
(la partie antérieure à @
) "PEUT être sensible à la casse" ... "DOIT ÊTRE traitée comme sensible à la casse" ... et pourtant "l'exploitation de la sensibilité à la casse des parties locales de boîte aux lettres entrave l'interopérabilité et est découragée."Aucune de ces expressions rationnelles n'applique de limite de longueur à l'adresse électronique globale, à la partie locale ou aux noms de domaine. La RFC 5322 ne spécifie aucune limite de longueur. Celles-ci découlent des limitations d'autres protocoles tels que le protocole SMTP pour l'envoi de courrier électronique. La RFC 1035 précise que les domaines doivent comporter 63 caractères au maximum, mais ne l'inclut pas dans sa spécification de syntaxe. La raison en est qu'un vrai langage normal ne peut pas imposer une limite de longueur et interdire les traits d'union consécutifs en même temps.
a-z
et A-Z
dans les classes de personnage?
~
vous êtes sensible à la casse, vous devez soit (a) ne pas utiliser de distinction de ~*
casse ou (b) avoir les lettres majuscules et minuscules dans la classe char.
citext
« s ~
semble être insensible à la casse pour moi, c'est la raison pour laquelle je demande.
J'utilise toujours CITEXT
pour le courrier électronique, car une adresse électronique est (en pratique) insensible à la casse , c'est-à-dire que John@Example.com est identique à john@example.com.
Il est également plus facile de configurer un index unique pour éviter les doublons, par rapport au texte:
-- 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)));
Comparer des courriels est également plus facile et moins sujet aux erreurs:
SELECT * FROM address WHERE email = 'JOHN@example.com';
comparé à:
SELECT * FROM address WHERE lower(email) = lower('JOHN@example.com');
CITEXT
est un type défini dans un module d'extension standard nommé "citext" , et disponible en tapant:
CREATE EXTENSION citext;
PS text
et varchar
sont pratiquement les mêmes dans Postgres et il n'y a pas de pénalité pour utiliser text
comme on peut s'y attendre. Cochez cette réponse: Différence entre text et varchar
J'utilise toujours varchar(254)
comme adresse e-mail ne peut pas dépasser 254 caractères.
Voir https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address
Postgresql n'a pas de type intégré pour les adresses e-mail, bien que je sois tombé sur un type de données ajouté.
De plus, vous pouvez souhaiter ajouter un déclencheur ou une telle logique pour normaliser les adresses électroniques au cas où vous souhaiteriez ajouter une clé unique.
En particulier, la domain
partie de l'adresse électronique (de la forme local-part
@ domain
est insensible à la casse, mais local-part
doit être traitée comme telle). Voir http://tools.ietf.org/html/rfc5321#section-2.4
Vous pouvez également enregistrer les noms et les adresses électroniques dans le formulaire "Joe Bloggs" <joe.bloggs@hotmail.com>
. Dans ce cas, vous devez disposer d'une chaîne de plus de 254 caractères et vous ne pourrez pas utiliser de manière significative une contrainte unique. Je ne le ferais pas et suggérerais de stocker le nom et l'adresse électronique séparément. De jolies adresses d'impression dans ce format sont toujours possibles dans votre couche présentation.
@
).
@
) = 320. Peut-être que je l’interprète mal.
Vous pourriez être intéressé par un chèque CONTRAINT (peut-être plus facile, mais vous pourriez en rejeter plus que vous ne le souhaitez, ou bien vous utilisez une fonction, abordée ici et ici . Fondamentalement, il s’agit essentiellement de compromis entre spécificité et facilité d’implémentation. Sujet intéressant Cependant, PostgreSQL a même un type d'adresse IP natif, mais il existe un projet sur pgfoundry pour un type de données de courrier électronique ici . Cependant, le meilleur que j'ai trouvé à ce sujet est un domaine de courrier électronique.. Le domaine est préférable à une contrainte de vérification, car si vous le modifiez, il vous suffit de le faire une fois dans la définition du domaine et de ne pas suivre les traces des tables parent-enfant en modifiant toutes vos contraintes de vérification. Les domaines sont vraiment cool - un peu comme les types de données, mais plus simple à implémenter. Je les ai utilisés dans Firebird - Oracle ne les a même pas!