Qual seria o tipo de dados correto para armazenar endereços de email no PostgreSQL?
Posso usar varchar
(ou até mesmo text
), mas me pergunto se existe um tipo de dados mais específico para emails.
Qual seria o tipo de dados correto para armazenar endereços de email no PostgreSQL?
Posso usar varchar
(ou até mesmo text
), mas me pergunto se existe um tipo de dados mais específico para emails.
Respostas:
DOMAIN
S personalizadosEu não acho que usar citext
(sem distinção entre maiúsculas e minúsculas) seja suficiente [1] . Usando o PostgreSQL, podemos criar um domínio personalizado que é essencialmente algumas restrições definidas sobre um tipo . Podemos criar um domínio, por exemplo, sobre o citext
tipo ou sobre text
.
type=email
especificação HTML5Atualmente, a resposta mais correta para a pergunta "qual é um endereço de email" está especificada no RFC5322 . Essa especificação é incrivelmente complexa [2] , tanto que tudo a quebra. O HTML5 contém uma especificação diferente para email ,
Esse requisito é uma violação intencional do RFC 5322, que define uma sintaxe para endereços de email que são simultaneamente muito rígidos (antes do caractere "@"), muito vagos (após o caractere "@") e muito relaxados (permitindo comentários) , caracteres de espaço em branco e seqüências de caracteres citadas de maneiras não familiares à maioria dos usuários) para serem úteis aqui. [...] A seguinte expressão regular compatível com JavaScript e Perl é uma implementação da definição acima.
/^[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])?)*$/
Provavelmente, é isso que você deseja e, se for bom o suficiente para HTML5, provavelmente será bom o suficiente para você. Podemos fazer isso diretamente no PostgreSQL. Também uso citext
aqui (o que tecnicamente significa que você pode simplesmente regex um pouco visualmente removendo as maiúsculas ou minúsculas).
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])?)*$' );
Agora você pode fazer ...
SELECT 'asdf@foobar.com'::email;
Mas não
SELECT 'asdf@foob,,ar.com'::email;
SELECT 'asd@f@foobar.com'::email;
Porque ambos retornam
ERROR: value for domain email violates check constraint "email_check"
Porque isso também é baseado no citext
SELECT 'asdf@foobar.com'::email = 'ASdf@fooBAR.com';
retorna true por padrão.
plperlu
/Email::Valid
Como uma observação importante, existe um método mais correto de fazer isso, que é muito mais complexo usando plperlu
. Se você precisa desse nível de correção, não deseja citext
. Email::Valid
pode até verificar se o domínio possui um registro MX (exemplo nos documentos de Email :: Valid)! Primeiro, adicione plperlu (requer superusuário).
CREATE EXTENSION plperlu;
Em seguida, crie a função , observe que marcamos como 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';
$$;
Em seguida, crie o domínio ,
CREATE DOMAIN validemail AS text NOT NULL
CONSTRAINT validemail_check CHECK (valid_email(VALUE));
citext
é tecnicamente errado. O SMTP define local-part
como diferencia maiúsculas de minúsculas. Mas, novamente, este é um caso de especificação sendo estúpida. Ele contém suas próprias crises de identidade. A especificação diz local-part
(a parte anterior a @
) "PODE ser sensível a maiúsculas e minúsculas" ... "DEVE ser tratada como maiúscula e minúscula" ... e ainda "explorar a sensibilidade de maiúsculas e minúsculas das peças locais da caixa de correio impede a interoperabilidade e é desencorajada".Nenhuma dessas expressões regulares impõe limites de tamanho no endereço de email geral ou na parte local ou nos nomes de domínio. O RFC 5322 não especifica nenhuma limitação de comprimento. Isso decorre de limitações em outros protocolos, como o protocolo SMTP, para realmente enviar email. O RFC 1035 afirma que os domínios devem ter 63 caracteres ou menos, mas não o incluem em sua especificação de sintaxe. O motivo é que um idioma comum verdadeiro não pode impor um limite de comprimento e não permitir hífens consecutivos ao mesmo tempo.
a-z
e A-Z
nas classes de personagens?
~
é sensível a maiúsculas e minúsculas, você precisa (a) usar ~*
maiúsculas e minúsculas ou (b) ter as letras maiúsculas e minúsculas na classe char.
citext
's ~
parece ser case-insensitive para mim, é por isso que eu estou pedindo.
Eu sempre uso CITEXT
para email, porque um endereço de email não diferencia maiúsculas de minúsculas , ou seja, John@Example.com é o mesmo que john@example.com.
Também é mais fácil configurar um índice exclusivo para evitar duplicatas, em comparação com o texto:
-- 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)));
Comparar e-mails também é mais fácil e menos propenso a erros:
SELECT * FROM address WHERE email = 'JOHN@example.com';
em comparação com:
SELECT * FROM address WHERE lower(email) = lower('JOHN@example.com');
CITEXT
é um tipo definido em um módulo de extensão padrão chamado "citext" e disponível digitando:
CREATE EXTENSION citext;
PS text
e varchar
são praticamente os mesmos no Postgres e não há penalidade por usar text
como se pode esperar. Verifique esta resposta: Diferença entre texto e varchar
Eu sempre uso varchar(254)
como endereço de email não pode ter mais de 254 caracteres.
Consulte https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address
O Postgresql não possui um tipo interno para endereços de email, embora eu tenha encontrado alguns tipos de dados contribuídos.
Além disso, você pode adicionar um gatilho ou uma lógica desse tipo para padronizar os endereços de email, caso deseje adicionar uma chave exclusiva.
Em particular, a domain
parte do endereço de email (que é do formato local-part
@ não domain
faz distinção entre maiúsculas e minúsculas e local-part
deve ser tratada como diferencia maiúsculas de minúsculas. Consulte http://tools.ietf.org/html/rfc5321#section-2.4
Outra consideração é se você deseja armazenar nomes e endereços de email no formulário "Joe Bloggs" <joe.bloggs@hotmail.com>
. Nesse caso, você precisa de uma sequência com mais de 254 caracteres e não poderá usar significativamente uma restrição exclusiva. Eu não faria isso e sugiro que armazene o nome e o endereço de email separadamente. Endereços de impressão bonitos neste formato sempre são possíveis em sua camada de apresentação.
@
).
@
) = 320. Talvez eu esteja interpretando errado.
Você pode estar interessado em usar uma verificação CONSTRAINT (possivelmente mais fácil, mas pode rejeitar mais do que gostaria ou usar uma FUNÇÃO discutida aqui e aqui . Basicamente, trata-se de compensações entre especificidade e facilidade de implementação. embora. PostgreSQL ainda tem um tipo de endereço IP nativa, mas há um projeto em pgFoundry para um tipo de dados de e-mail aqui . no entanto, o melhor que eu encontrei sobre este é um e-mail de domínio. O domínio é melhor do que uma restrição de verificação, porque, se você o alterar, é necessário fazê-lo apenas uma vez na definição de domínio e não seguir as trilhas das tabelas pai-filho, alterando todas as restrições de verificação. Os domínios são realmente legais - como tipos de dados, mas mais simples de implementar. Eu os usei no Firebird - a Oracle nem os possui!