AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 37014
Accepted
Thronk
Thronk
Asked: 2013-03-20 06:30:10 +0800 CST2013-03-20 06:30:10 +0800 CST 2013-03-20 06:30:10 +0800 CST

我应该以什么数据类型将电子邮件地址存储在数据库中?

  • 772

我知道 254 个字符的电子邮件地址是有效的,但我研究过的实现倾向于使用 varchar(60) 到 varchar(80) 或等效的。例如:此 SQL Server 建议使用 varchar(80) 或此 Oracle 示例

是否有理由不使用最大 254 个字符?根据定义,varchar 不是只使用存储数据所需的存储空间吗?

是否存在显着的性能影响/权衡导致如此多的实现使用少于全部 254 个可能的字符?

database-design datatypes
  • 7 7 个回答
  • 178261 Views

7 个回答

  • Voted
  1. Best Answer
    Aaron Bertrand
    2013-03-20T06:59:27+08:002013-03-20T06:59:27+08:00

    我一直用varchar(320),但真的应该是varchar(319)。这就是为什么。该标准规定了以下限制:

    • “本地部分”(用户名)为64 个字符。
    • @符号1 个字符。
    • 域名的254 个字符(我一直相信 255,但根据这个勘误表我错了- 它实际上是 256 减去可能的<周围尖括号>)。

    现在,有些人会说您需要支持的不仅仅是这些。有些人还会说您需要为域名支持 Unicode(这意味着您必须切换到 Unicode nvarchar)。虽然标准可能会在此期间发生变化(我已经有一段时间没有参与游戏了),但我非常有信心,此时世界上大多数服务器都不会接受 Unicode 电子邮件地址,我敢肯定许多服务器在创建和/或接受大于 319 个字符(可能大于 254/255/256)的地址时会遇到问题。一个合理的上限应该更像是 128 个字符,因为实际上,比这更长的 e-amil 地址根本不实用,即使它们是在某些服务之外自动完成的。

    也就是说,您现在可以为最坏的情况做好准备,如果您愿意(并且如果您在 SQL Server 2008 R2 或更高版本中使用数据压缩,您将受益于 Unicode 压缩,这意味着您只需为实际需要的字符支付 2 字节的损失它)。这样,您可以使您的专栏尽可能宽,并且您可以让人们在其中塞入他们想要的任何太长的垃圾 - 如果他们给您垃圾,他们就不会收到电子邮件,就像他们不会一样如果插入失败,将收到一封电子邮件。问题是如果你让无效的垃圾进入,你必须处理它。而且无论您制作什么大小 - 如果有人试图将 400 个字符填充到 319 个字符的列中,那么有人会尝试将 1025 个字符填充到 1024 个字符的列中。任何明智的人都没有理由拥有大于 319 个字符的电子邮件地址,除非他们使用它来明确测试系统边界。

    但我认为我们需要停止就此征求意见- 并停止查看其他实现以寻求指导(在这种情况下发生的情况是,您引用的那些没有费心做自己的功课,只是从中挑选数字,嗯,你知道的)。您可以直接访问该标准- 确保您查阅最新版本,至少支持该标准,并保持在标准之上,以便您可以适应规范的变化。


    编辑感谢@ypercube 在聊天中的 ping。

    顺便说一句,也许您一开始就不想将整个地址转储到单个列中。规范化可能表明您不想存储@hotmail.com1500 万次,因为更精简的 FK int 可以正常工作并且没有可变长度列的额外开销。您还可以规范化用户名,[email protected]并[email protected]共享一个共同的用户名 - 他们彼此不认识,但您的数据库并不关心这一点。

    我在这里谈到了一些:

    • 在 SQL Server 中更有效地存储电子邮件地址
    • 在 SQL Server 中更有效地存储电子邮件地址 - 第 2 部分

    然而,这对上述 254 个字符的限制提出了挑战,因为对于将有效的 255 个字符的域与有效的 1 个字符的本地部分组合时会发生什么似乎并没有达成共识。这应该被世界上大多数服务器接受,但似乎违反了这个 254 个字符的限制。那么,当域可以重新用作有效的 255 个字符的 URL时,您是否会创建一个Domains人为地降低电子邮件地址长度限制的表?


    编辑有一条评论:

    想为 postgres 添加这个,不要使用 varchar(n) wiki.postgresql.org/wiki/…

    也许你可以在电子邮件列上使用检查约束

    虽然我同意“无限”字符串列的用例,但这不是其中之一。当您从完善的标准中了解数据域时,您应该使用它们。该链接讨论了如果您选择不当,这可能会导致最终用户出错。所以呢?没有理由让人们在域之外插入值(例如,一个 6 亿字符长的电子邮件地址),以免他们这样做时出错。事实上,我认为电子邮件正是链接所讨论的那种反例。

    至少在 SQL Server 中正确定义列意味着您不会遭受记录在案的类型性能损失或max由于varchar/nvarchar声明太宽而浪费内存。虽然使用检查约束来限制长度使得以后在任一方向上调整最大长度变得更加容易,但这似乎与正确的列定义相比没有任何其他好处(用户无论哪种方式都会出错)。

    • 57
  2. Thomas Stringer
    2013-03-20T06:45:45+08:002013-03-20T06:45:45+08:00

    这个决定有几个考虑因素。首先也是最重要的是使用数据必须符合的必要限制的当前和未来预测。varchar(1024)当您只存储不应超过 32 个字符的字符串(强调should关键字)时,您不想将每个字符串列数据类型设置为这是有原因的。

    如果您有某种漏洞,将电子邮件全部修改为 255 个字符,那么您可能会对页面拆分产生长期的性能影响。这可能看起来不寻常,而且很可能是这样,但您需要根据业务需求调整数据大小。就像数据库与应用程序辩论中的古老约束一样,我坚信数据类型限制和允许值也应该在数据层强制执行。

    这让我想到了下一点。数据库很可能只是数据层。应用层使用什么?例如,如果您有一个应用程序,您只能为电子邮件地址输入 80 个字符,那么您为什么希望数据类型更大呢?企业需要回答两个问题:

    1. 会是什么?
    2. 应该是什么?

    只有这样你才会有答案。

    根据定义,varchar 不是只使用存储数据所需的存储空间吗?

    是和不是。可变长度数据将有一种偏移量来记录它的长度。

    • 7
  3. avakharia
    2013-03-20T06:58:57+08:002013-03-20T06:58:57+08:00

    RFC 5321(当前的 SMTP 规范,已废弃 RFC2821)指出:

    用户名或其他本地部分的最大总长度为 64 个八位字节。域名或号码的最大总长度为 255 个八位字节

    所以 64 + 255 + @ 符号意味着 VARCHAR(320)。您可能永远不需要这么多,但以防万一,拥有它是安全的。

    • 5
  4. Greenstone Walker
    2013-03-20T22:46:31+08:002013-03-20T22:46:31+08:00

    作为对已经在这里的出色答案的评论:

    首先,如果您已经创建了字段 asvarchar(240)并且您想稍后将其更改为更长的字段,例如varchar(320),那么此更改应该是数据库服务器上的一个微不足道的操作 - 当然,这取决于您的数据库产品。

    alter table Schema.Object alter column EmailAddress varchar(320) ;
    

    其次,根据平均行大小和页大小,使用varchar(320)代替varchar(240)可能不会改变分配的页数(表实际占用的磁盘空间)。

    第三,上面有人谈到验证电子邮件地址。我认为只有一种确定的方法可以验证电子邮件地址,那就是向它发送电子邮件。:-)

    • 3
  5. DocSalvager
    2013-03-28T00:59:05+08:002013-03-28T00:59:05+08:00

    VARCHAR 的任何变体仅使用数据块中所需的空间。与使用固定长度 CHAR 所浪费的空间相比,用于存储长度的额外字节是微不足道的。

    由于 VARCHAR 列长度实际上是“最大长度”,因此在任何情况下都应将其设置为大于可能的最大长度。只会使用每行所需的空间。然后应用程序应该设计有滚动字段或任何基于典型值有意义的东西。

    数据库设计就像一张物理纸,它规定了大小的硬性限制。纸页无法放大。在这个比喻中,应用程序就像打印在页面上的表格。可以做很多事情来调整我们可以在表单中保存多少数据。

    尽管增加 VARCHAR 大小的命令可能看起来很简单并且可以立即在小表上运行,但在具有数千行或更多行的表上这样做可能需要某种数据库静默,同时重新生成所有数据和索引块。一种方法是将所有内容复制到具有较大列的新表中。无论使用什么技术,这都是一笔大买卖。因此,一旦加载生产表,您应该考虑 VARCHAR 列大小在很大程度上是不可变的。

    • 2
  6. Kin Shah
    2013-03-20T06:47:17+08:002013-03-20T06:47:17+08:00

    VARCHAR 是用于电子邮件地址的最佳数据类型,因为电子邮件的长度变化很大。NVARCHAR 也是一种替代方法,但我建议仅在电子邮件地址包含扩展字符时使用它,并且请记住,与 VARCHAR 相比,它需要双倍的存储空间。

    在我的环境中,我们使用 varchar(70),因为我遇到的最长的是 60-70 字符长,但这也取决于贵公司的客户群。此外,作为旁注,请确保您对电子邮件地址的有效性进行了一些电子邮件验证检查。例如使用检查约束或 CHARINDEX

    • 1
  7. Evan Carroll
    2017-03-03T08:21:41+08:002017-03-03T08:21:41+08:00

    使用 SQLDOMAIN

    如果您使用的是企业数据库服务器,则应该以某种方式将电子邮件地址存储为DOMAIN具有某种程度的有效性。域在 SQL 规范中指定

    域是一个命名的用户定义对象,在可以指定数据类型的某些地方,可以将其指定为数据类型的替代。域由数据类型、可能的默认选项和零个或多个(域)约束组成。

    例如,免费和开源的 PostgreSQL 支持这一点,除非您对规范的实施有任何限制,否则该列本身包含有效的电子邮件。例如你可以..

    • DOMAIN通过电子邮件的 HTML5 规范创建自定义。
    • 或者,通过电子邮件的 RFC822、RFC2822、RFC5322 规范。
    • 创建一个自定义DOMAIN,在检查时检查服务器的 MX 记录。

    我在这个特定于 PostgreSQL 的答案中评估这些选项

    • 1

相关问题

  • MySQL VARCHAR 和 TEXT 数据类型有什么区别?

  • INT(5) vs SMALLINT(5):数字类型后面括号中的数字

  • 存储计算值或根据要求重新计算它们更好吗?[复制]

  • 存储与计算聚合值

  • 在数据仓库中实现多对多关系有哪些方法?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve