Qual seria o tipo de dados correto para armazenar endereços de e-mail no PostgreSQL?
Posso usar varchar
(ou até text
), mas gostaria de saber se existe um tipo de dado mais específico para emails.
Qual seria o tipo de dados correto para armazenar endereços de e-mail no PostgreSQL?
Posso usar varchar
(ou até text
), mas gostaria de saber se existe um tipo de dado mais específico para emails.
DOMAIN
s personalizadosEu não acho que usar
citext
(não diferencia maiúsculas de minúsculas) é 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 exemplocitext
, sobre o tipo ou sobretext
.type=email
Usando a especificação HTML5Atualmente, a resposta mais correta para a pergunta o que é um endereço de e-mail é especificada em RFC5322 . Essa especificação é insanamente complexa [2] , tanto que tudo a quebra. HTML5 contém uma especificação diferente para e-mail ,
Isso é provavelmente o que você quer, e se for bom o suficiente para HTML5, provavelmente é bom o suficiente para você. Podemos fazer uso disso diretamente no PostgreSQL. Eu também uso
citext
aqui (o que tecnicamente significa que você pode simplesmente o regex visualmente removendo as letras maiúsculas ou minúsculas).Agora você pode fazer...
Mas não
Porque ambos retornam
Porque isso também é baseado no citext
retorna verdadeiro por padrão.
Usando
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, você não quercitext
.Email::Valid
pode até verificar se o domínio tem um registro MX (exemplo na documentação de Email::Valid)! Primeiro, adicione plperlu (requer superusuário).Em seguida , crie a função , observe que marcamos como um
IMMUTABLE
:Em seguida , crie o domínio ,
Notas de rodapé
citext
é tecnicamente errado. SMTP definelocal-part
como sendo sensível a maiúsculas e minúsculas. Mas, novamente, este é um caso da especificação ser estúpida. Ele contém suas próprias crises de identidade. A especificação dizlocal-part
(a parte antes do@
) "Pode diferenciar maiúsculas de minúsculas" ... "Deve ser tratada como sensível a maiúsculas" ... e ainda "explorar a distinção entre maiúsculas e minúsculas das partes locais da caixa de correio impede a interoperabilidade e é desencorajada".Eu sempre uso
CITEXT
para email, porque um endereço de email (na prática) não diferencia maiúsculas de minúsculas , ou seja, [email protected] é o mesmo que [email protected].Também é mais fácil configurar um índice exclusivo para evitar duplicatas, em comparação com o texto:
Comparar e-mails também é mais fácil e menos propenso a erros:
em comparação com:
CITEXT
é um tipo definido em um módulo de extensão padrão chamado "citext" e disponível digitando:PS
text
evarchar
são praticamente os mesmos no Postgres e não há penalidade por usartext
como se pode esperar. Verifique esta resposta: Diferença entre texto e varcharEu sempre uso
varchar(254)
como um endereço de e-mail 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 tem um tipo embutido para endereços de e-mail, embora eu tenha encontrado alguns tipos de dados contribuídos.
Além disso, você pode querer adicionar um gatilho ou alguma lógica desse tipo para padronizar os endereços de e-mail caso deseje adicionar uma chave exclusiva a ele.
Em particular, a
domain
parte do endereço de e-mail (que tem o formatolocal-part
@domain
não diferencia maiúsculas de minúsculas, enquantolocal-part
deve ser tratada como diferencia maiúsculas de minúsculas. Consulte https://www.rfc-editor.org/rfc/rfc5321#section-2.4Outra consideração é se você deseja armazenar nomes e endereços de e-mail no formulário
"Joe Bloggs" <[email protected]>
; nesse caso, você precisa de uma string com mais de 254 caracteres e não poderá usar significativamente uma restrição exclusiva. Eu não faria isso e sugiro armazenar o nome e o endereço de e-mail separadamente. Endereços de impressão bonitos neste formato são sempre possíveis em sua camada de apresentação.Você pode estar interessado em usar um
CHECK CONSTRAINT
(possivelmente mais fácil, mas pode rejeitar mais do que gostaria, ou usar uma FUNCTION, discutida aqui e aqui ). Você pode usar um regex com a restrição.Você poderia fazer algo assim:
O
~*
operador corresponde sem distinção entre maiúsculas e minúsculas . O regex( 1 ) pode ser tão complexo quanto você quiser - veja esta resposta magistral que contém uma referência a um regex definitivo com 6.509 caracteres!Basicamente, trata-se de compensações entre especificidade e facilidade de implementação. Mesmo assim, tópico interessante. O PostgreSQL tem até um tipo de endereço IP nativo, mas existe um projeto no pgfoundry para um tipo de dados de email aqui .
No entanto, o melhor que encontrei sobre isso é um domínio de e-mail . O domínio é melhor do que uma restrição de verificação porque se você alterá-lo, você só precisa fazer isso uma vez na definição do domínio e não seguir as trilhas das tabelas pai-filho alterando todas as suas restrições de verificação.
Os domínios são muito legais - como tipos de dados, mas mais simples de implementar. Eu os usei no Firebird - o Oracle nem os tem!
1) exemplo descaradamente retirado daqui
Não existe um tipo de dados como 'email', mas ainda podemos usar regexp no PostgreSQL. Então, vamos aproveitar.
A primeira coisa que você gostaria de fazer é:
CREATE EXTENSION citext;
Esse tipo de dados é para textos que diferenciam maiúsculas de minúsculas. Portanto, não importa se o texto está em letras maiúsculas ou minúsculas, o Postgres irá usar ambos como o mesmo texto.Agora aqui, você está aplicando o regexp à sua coluna.
person_email
A propósito, o regexp é meio ilustrativo, existem maneiras melhores de validar um email.Para o registro, o tipo de dados em
person_gender
é um tipo personalizadoemail.sql
- validação mínima básica, mas rápida. Porque a validação será acionada toda vez em umaUPDATE
consulta, mesmo que o valor do campo não tenha sido alterado!is_email.sql
- validação quase de acordo com a especificação, mas lenta.