代码之家  ›  专栏  ›  技术社区  ›  Sean Hanley

在数据库中使用整数列存储邮政编码是个好主意吗?

  •  47
  • Sean Hanley  · 技术社区  · 16 年前

    乍一看,我似乎有两个基本的存储选择 ZIP codes 在数据库表中:

    1. 文本(可能最常见),即 char(5) varchar(9) 支持+4扩展
    2. 数字,即32位整数

    如果我们假定不存在国际问题,这两种方法都将满足数据的要求。在过去,我们通常只是走文本路线,但我想知道是否有人做了相反的事情?简而言之,整数方法有两个明显的优点:

    • 就其性质而言,它仅自动限制为数字(而在没有验证的情况下,文本样式可以存储字母,据我所知,这些字母在邮政编码中是无效的)。这个 不过,这意味着我们可以/愿意/应该放弃正常验证用户输入!
    • 它占用的空间更少,是4个字节(即使是9位数的邮政编码也应该足够),而不是5或9个字节。

    而且,它似乎不会对显示输出造成太大的影响。打一个耳光是微不足道的 ToString() 在数值上,使用简单的字符串操作为+4扩展名插入连字符或空格或其他内容,并使用字符串格式恢复前导零。

    有什么不鼓励使用的吗 int 作为我们的数据类型,只有邮政编码?

    11 回复  |  直到 7 年前
        1
  •  109
  •   S.Lott    16 年前

    一个数字邮政编码——在很小的程度上——具有误导性。

    数字应该意味着什么 数字的 .邮政编码不加、减或参与任何数字运算。12309-12345不计算从斯克内克塔迪市中心到我的邻居的距离。

    当然,对于邮政编码,没有人会感到困惑。但是,对于其他类似数字的字段,它可能会令人困惑。

    由于邮政编码不是数字——它们恰好是用受限的字母编码的——我建议避免使用数字字段。1字节的节省值不多。我认为 意思 比字节更重要。


    编辑 .

    “至于前导零……”是我的观点。数字没有前导零。邮政编码上有意义的前导零的存在是证明它们不是数字的另一个证据。

        2
  •  24
  •   Tom    16 年前

    你打算储存非美国邮政编码吗?加拿大有6个字符和一些字母。我通常只使用10个字符的字段。磁盘空间很便宜,不需要重新编写数据模型。

        3
  •  17
  •   Community CDub    8 年前

    使用带验证的字符串。邮政编码可以以0开头,因此数字不是合适的类型。此外,这也适用于国际邮政编码(如英国,最多8个字符)。在不太可能出现邮政编码瓶颈的情况下,您可以将其限制为10个字符,但请检查 target formats 第一。

    Here are 英国、美国和加拿大的验证规则。


    是的,你可以用pad把前导的0取回来。然而,从理论上讲,您正在丢弃可能在出现错误时有所帮助的信息。如果有人在数据库中找到1235,是原来的01235,还是漏掉了另一个数字?

    最佳实践是说你应该说出你的意思。邮政编码是代码,不是数字。你要去吗 add/subtract/multiply/divide 邮政编码?从实用的角度来看,更重要的是你要排除长拉链。

        4
  •  9
  •   TheTXI    16 年前

    通常,您将使用非数字数据类型,如varchar,它将允许更多的邮政编码类型。如果您设置为仅允许5位[XXXX]或9位[XXXX-XXXX]邮政编码,那么您可以使用char(5)或char(10),但我不推荐使用。varchar是最安全和最理智的选择。

    编辑:还应注意,如果您不打算对字段进行数值计算,则不应使用数值数据类型。邮政编码不是一个数字,在这个意义上,你加或减它。它只是一个通常由数字组成的字符串,因此您应该避免对其使用数字数据类型。

        5
  •  7
  •   BenAlabaster    16 年前

    从技术角度来看,这里提出的一些观点是相当微不足道的。我使用地址数据清理 每日的 基础-特别是清理来自世界各地的地址数据。这不是一个微不足道的任务,任何延伸的想象。当涉及到邮政编码时, 能够 将它们存储为整数,尽管它在语义上可能不正确。事实上,数据是一个数字形式,不管严格地说,是否 在值中被认为是数字。

    但是,将它们存储为数字类型的真正缺点是,您将无法轻松查看数据是否输入错误(即缺少值),或者系统是否删除了前导零,从而导致成本高昂的操作,以验证可能无效的邮政编码是否正确。

    如果其中一个影响是业务延迟,那么强制用户输入正确的数据也是非常困难的。如果数据不明显,用户通常没有耐心输入正确的数据。使用regex是确保正确数据的一种方法,但是,如果用户输入的值不一致,并且显示错误,则可能会完全忽略该值或输入符合但不正确的值。[使用加拿大邮政编码]的一个例子是,您经常看到输入的a0a0无效,但符合加拿大邮政编码的regex。通常情况下,这是由被迫提供邮政编码的用户输入的,但他们要么不知道邮政编码是什么,要么不完全正确。

    一个建议是将整个条目作为一个单元进行验证,验证邮政编码与地址的其余部分相比是否正确。如果不正确,那么为地址提供备用的有效邮政编码将使他们更容易输入有效数据。同样,如果街道地址的邮政编码正确,但街道编号不在该邮政编码的域内,则为该邮政编码/街道组合提供备用街道编号。

        6
  •  2
  •   V'rasana Oannes    16 年前

    除非您有对邮政编码数据进行数学计算的业务需求,否则使用int是没有意义的。您过于工程化了。

    希望这有帮助,

    比尔

        7
  •  2
  •   kexx    9 年前

    不,因为

    • 你从不在邮政编码上做数学运算
    • 可能包含破折号
    • 可以从0开始
    • 对于标量类型,空值有时解释为零。 像整数(例如,以某种方式导出数据时)
    • 邮政编码,即使是一个数字,也是一个地区的名称, 这意味着这是一个名称,而不是任何数字量
        8
  •  1
  •   benc    15 年前

    如果您考虑的话,邮政编码实际上是一个编码的名称空间。传统数字,但也有连字符和大写字母:

    “10022-鞋子”

    http://www.saksfifthavenue.com/main/10022-shoe.jsp

    实际上,许多业务应用程序不需要支持这种边缘情况,即使它是有效的。

        9
  •  0
  •   Eric Petroelje    16 年前

    整数很好,但它只在美国有效,这就是大多数人不这样做的原因。通常我只使用varchar(20)左右。可能对任何地方都是杀戮过度。

        10
  •  0
  •   Steve    15 年前

    如果您要为我们使用一个整数zips,您需要将前导部分乘以10000,然后加上+4。数据库中的编码与输入验证无关。您可以随时要求输入有效与否,但是存储取决于您认为您的需求或USPS将发生多大的变化。(提示:您的要求 改变。

        11
  •  0
  •   therealrodk    7 年前

    learned recently 在Ruby中,您希望避免出现这种情况的原因之一是,有一些以前导零开头的邮政编码,如果以整数形式存储,则会自动转换为八进制。

    the docs :

    可以使用特殊前缀以十进制、十六进制、八进制或二进制格式写入数字。对于十进制数,使用前缀0d;对于十六进制数,使用前缀0x;对于八进制数,使用前缀0或0o_