2012-12-08 33 views
2

這是一個老問題的具體實例:如何在SQL數據庫中存儲「號碼」(例如電話號碼,IP地址,社會安全號碼)?SQL中的瑞典語「personnummer」(個人身份號碼)

背景:在瑞典,個人識別號碼(「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.0.0.1」與2130706433相比)。

我讚賞INTEGER專欄的「嚴格性」,但也認爲這可能會遇到看不見的問題。

編輯:我們有一個真正的需要驗證這個輸入與校驗和等等,這需要做個人數字(乘法,求和等)的數學。由於數字不是真的......呃......數量的一部分,而是十進制格式,所以最終認爲它是一個varchar是有意義的。

+0

將它存儲爲一個varchar並創建一個檢查約束(例如使用正則表達式)來驗證內容(只有數字,最少10個字符等) –

+0

如何在javascript中驗證它? –

+0

@YatinMistry我認爲這個問題有點偏離主題。使用簡單的[Luhn算法](https://en.wikipedia.org/wiki/Luhn_algorithm)完成personummer的驗證。通過谷歌搜索,我發現了一個[使用jQuery實現](https://github.com/wallin/jquery-validate-personnummer),但創建自己的代碼很簡單。 – vicvicvic

回答

1

使用VARCHAR具有固定長度,因爲它是最簡單的方法。我認爲你的組織不會存儲所有9個數字。500萬居民使節約空間成爲真正的設計目標? :)

+0

不,這是真的,這就是爲什麼我覺得有點傻...我們只有大約3000名成員,所以節省大約300 KB,這不是真正需要關心的東西。 – vicvicvic

+0

我更喜歡簡單的方式,主要是因爲維護和其他人也必須閱讀和理解代碼的原因。除非你真的依賴速度/空間/ ...,那麼簡單通常與快/小/ ...相反 –

1

所以,據我所知,連字符/加號僅適用於2位數年份的格式。

如果我是你,我會在應用程序端轉換爲4位數的年份格式(並放下連字符)。然後將結果值存儲爲整數。正如你所說的那樣,這將節省空間,並且可以讓你對數值進行數學轉換(儘管我認爲在個人數字上這可能是無關緊要的)。

我認爲這裏的關鍵是您應該選擇單一格式而不是試圖管理數據庫中的兩種不同格式。這也將有助於提高應用程序的一致性。當涉及需要一種或另一種格式的外部應用程序時,您可以將轉換放置到傳輸代碼中。

在一個側面說明,它應該是相當瑣碎創建一個觸發器,它會自動分配2位數的年份格式(只要你替換連字符/加有數字),4年的格式。

+0

右連字符只是一個格式化的東西,有12位數字。關於數學:我們想要實現校驗和算法來驗證數字(類似於Luhn但不一樣)。我認爲使用數字中的單個數字比字符串更容易處理,儘管... – vicvicvic

+0

是的......如果您需要執行校驗和,那麼varchar可能更容易處理。我認爲我在單一格式問題上的觀點仍然存在:)如果你確實選擇了一種格式,你可以將它設置爲char(長度)而不是varchar(這應該有助於空間問題) –

+0

你(和bowmore)是正確的CHAR當然。謝謝! – vicvicvic

1

我會將規範形式201201013842存儲爲CHAR(而不是VARCHAR)。

底線是你不控制數字的語義(瑞典當局)。如果他們決定在數字中添加非數字字符(因爲數字已經以舊格式),那麼你將會更好地處理這種變化。

+0

這是一個很好的觀點。然而,由於「120101-3842」是「官方」形式(以存在的形式存在),我想說你的典型論證是贊成那個。如果當局決定用斜線替代連字符以指定某些內容會怎麼樣呢?如果你使用長而非官方的形式,那麼這是毫無意義的,但是,正如你所暗示的那樣,誰知道未來會帶來什麼。 – vicvicvic

+0

你將用作規範形式的選擇影響較小。重要的是所有數字都存儲在一樣的方法。我的偏好有兩點:YYYYMMDD格式似乎成爲新的標準,從中提取出生日期的邏輯更簡單。 – bowmore

1

我們有同樣的問題,我們目前將其存儲爲yyyyMMdd-xxxx,但如果我在哪裏今天這個重新設計我將存儲yyyyMMdddate領域,因爲這將處理日期的驗證,那麼我會儲存4其他值在一個nchar(4)並添加一個約束來確保其唯一的數字。

+0

爲什麼麻煩驗證第十個字符已經是[校驗和](https://en.wikipedia.org/wiki/Personal_identity_number_%28Sweden%29#Checksum)的所有其他數字的日期?你爲什麼不使用它來驗證? – eis

+0

@eis在日期不正確的情況下,校驗和可以是正確的,這並不意味着它是有效的人員。 – Peter