SQL中的瑞典语“personnummer”(个人身份号码)

时间:2012-12-08 16:54:19

标签: sql database normalization

这是一个老问题的具体实例:如何在SQL数据库中存储“数字”(例如电话号码,IP地址,社会安全号码)?

背景:在瑞典,个人身份号码(“personnummer”)极为常见:您在与政府,银行,雇主等沟通时使用它们。瑞典出生的人在出生时就会被分配。我的移民朋友在他们找到一个人之前几个星期就对这对黑暗的朋友感到悲伤,最终可以获得借记卡并开始寻找工作。

我的组织需要存储我们会员的人数。我们有一个SQL数据库。 我应该如何存储数据?


来自维基百科,关于personnummer的格式:

  

个人识别码由10位数字和连字符组成。前六个对应于人的生日,以YYMMDD形式。它们之后是连字符。 100岁以上的人用加号替换连字符。第七到第九是序列号。将奇数第九个数字分配给男性,将偶数第九个数字分配给女性。一些县政府,如斯德哥尔摩和一些银行,已经开始使用12位数字来允许YYYYMMDD。这种格式也用于一些瑞典身份证[需要澄清]和瑞典欧洲健康保险卡,但不用于国家颁发的身份证件。

     

第十位数字是校验和,它是在1967年系统计算机化时引入的。

因此,对于今年出生的人来说,一个人可能是“120101-3842”。由于Y2K和“用加号替换连字符”,这通常也被格式化为“20120101-3842”并不为人所知。

在数据库专栏中,我想我可以:

  • 将其存储为VARCHAR,格式为“120101-3842”,“20120101-3842”或“201201013842”(通过获取YYYYMMDD格式的多余连字符来删除字节)。
  • 将完整的YYYYMMDDXXXX存储为INTEGER,这对于32位来说太大了,但在64位中没有问题。

在这种情况下,前导零没有任何问题,并且使用VARCHAR的大小几乎是其两倍。与IP地址不同,将此数字存储为INTEGER并不会使人类更难阅读(即“{127}”与2130706433相比)。

我很欣赏INTEGER专栏的“严格性”,但也觉得这可能会遇到看不见的问题。

编辑:我们真的需要用校验和等来验证这个输入,这需要对单个数字进行数学运算(乘法,求和等)。由于数字不是真的...呃...数量的一部分,但是十进制格式,毕竟将它视为varchar可能是有意义的。

4 个答案:

答案 0 :(得分:1)

使用具有固定长度的VARCHAR,因为这是最简单的方法。而且我不认为你的组织将存储所有950万居民的数量,以便节省空间是一个真正的设计目标? :)

答案 1 :(得分:1)

因此,据我所知,只有2位数年份的格式才需要连字符/加号。

如果我是你,我会在应用程序端转换为4位数年份格式(并删除连字符)。然后将结果值存储为整数。正如您所说,这将节省空间,并允许您在数学上转换值(虽然我想在个人数字上这可能是无关紧要的。)

我认为关键在于您应该选择单一格式,而不是尝试在数据库中管理两种不同的格式。这也有助于提高应用程序的一致性。对于需要一种或另一种格式的外部应用程序,您可以将转换放入转移代码中。

另一方面,创建一个自动分配2位数年份格式的触发器(只要用数字替换连字符/加号)到4年格式应该是相当简单的。

答案 2 :(得分:1)

我会将规范形式201201013842存储为CHAR(而不是VARCHAR)。

最重要的是你不能控制数字的语义(瑞典当局这样做)。如果在某些时候他们决定在数字中添加非数字字符(就像旧格式中的数字一样),您将能够更好地处理更改。

答案 3 :(得分:1)

我们遇到了同样的问题,我们目前将其存储为yyyyMMdd-xxxx,但如果我今天在哪里重新设计,我会将yyyyMMdd存储在date字段中,因为它会处理验证日期,然后我将其他4个值存储在nchar(4)中并添加约束以确保其唯一的数字。