2

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

背景:在瑞典,个人身份证号(“personnummer”)非常普遍:您在与政府、银行、您的雇主等沟通时使用它们。在瑞典出生的人在出生时就被分配了它们。我的移民朋友们在获得个人号码并最终获得借记卡并开始寻找工作之前的几周内感叹黑暗。

我的组织需要存储我们成员的 personnummer。为此,我们有一个 SQL 数据库。我应该如何存储数据?


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

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

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

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

在数据库列中,我想我可以:

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

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

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

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

4

4 回答 4

1

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

底线是您无法控制数字的语义(瑞典当局会这样做)。如果在某个时候他们决定在数字中添加非数字字符(就像旧格式中的数字一样),您将能够更好地应对这种变化。

于 2012-12-08T17:17:09.007 回答
1

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

于 2012-12-08T17:03:53.960 回答
1

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

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

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

附带说明一下,创建一个触发器应该相当简单,该触发器会自动将 2 位数年份格式(只要您用数字替换连字符 / 加号)分配给 4 年格式。

于 2012-12-08T17:06:13.097 回答
1

我们有同样的问题,我们目前将其yyyyMMdd-xxxx存储yyyyMMdddate) 并添加一个约束以确保其唯一的数字。

于 2014-11-27T14:51:26.187 回答