2011-08-24 54 views
0

我被要求使用一個數據庫,其中大多數主鍵和其他字段也使用char(n)來存儲帶有填充的數值,例如:MySQL:使用char(n)與使用零填充的十進制(n)

product_id: char(8) [00005677] 
user_id: char(6) [000043] 
category_id: char(2) [05] 

他們想用它這樣的原因,是爲了能夠使用的字符(在遙遠的未來),如果他們想要的。然而,他們有許多基於數字的規則,例如,從01到79的category_id對應於一般類別,並且從80到89是特殊類別,而90到99是用戶定義的類別。

我個人認爲使用char(n)來存儲數字是一種不好的做法。我的理由是:

  1. 使用char,「」!= 0,0!= 00,05!= 5,00043!= 000043等等。因此, 的值必須經常檢查(以防止數據損壞)。
  2. 如果我墊了一些:0 - > 00,那麼我要注意不要墊 字符(A - > 0A)
  3. 如果使用的字符,然後範圍變得怪怪的,是這樣的: 從01〜79和AB和RX和TZ和S,等...
  4. 索引號代替字符導致性能增益

我提議將其改爲十進制(N)與ZEROFILL到使其更加「防錯」,因爲這些信息被不同的來源(網絡,Windows客戶端,上傳CSV)修改。例如,如果他們想要添加更多類別,那麼從小數點(2)更新爲小數點(3)會更容易。

我的問題是:我錯了嗎? char(n)可以被這個任務信任嗎?如果「字符」是邪惡的數字,那麼我在上面的列表中缺少哪些其他缺點(如果我想贏得我的情況,我可能需要更好的理由)?

TIA(任何評論/答案將不勝感激)。

+0

我會接受誰能說服我的答案,使用char(n)這種方式是完全安全的,或者可以給我更多理由說明爲什麼不使用char。 – lepe

+2

@lepe:基於「最佳實踐」,案件本身是荒謬的。領先的零與存儲無關,但只與演示有關。只要您希望您的ID以前導零顯示 - 請在**之前將它們**輸出給用戶,並以您喜歡的任何格式進行存儲。 – zerkms

+0

+1。我完全同意你...恕我直言,突然使用chars通常只有數字被使用可能會打破未來的事情。唯一的原因是他們想記住字符的數量(這是:99,AA(2個字符); 100(3個字符))。但我認爲這不值得複雜化。如果有必要的話,增加數字只是更容易......但向他們解釋! :S – lepe

回答

1

如果這是SQL Server或Oracle或任何其他RDBMS,我會建議執行這些列的檢查約束,使數據總是匹配列的全部容量 - 這將確保您的標識符是統一的。

不幸的是MySQL doesn't support this

雖然它不會阻止對進入數據庫或搜索例程,客戶端或數據庫中的procs的事物進行填充的煩惱,但它可以保證字段在最低級別上是乾淨的。

我發現使用這樣的約束有助於避免事情變得非常失控。

就使用數字進行優化而言,如果它們在將來需要容納非數字字符,那不會是一種選擇。

使用varchar/char數據擁有自然鍵(可能是主鍵的候選對象)是非常普遍的,但是卻改爲對替代鍵實施參照完整性(通常是某種自動編號整數,它只是一個內部參考,並且通常是聚集索引和主鍵)。

+0

是的,使用觸發器來填充數據可能是一個選項... CHECK可以讓我的生活更輕鬆,我猜...但我堅持使用MySQL。 因此,基本上你說過,如果沒有這些CHECK,你的數據可能會非常失控?很久以前,我提出使用內部的AUTOCOUNT引用,但他們拒絕這個想法,因爲數據的一部分直接從每個Windows客戶端導入,他們認爲這會讓它複雜化。 – lepe

+1

@lepe如果你無法在數據庫中執行它,任何事情都可能發生。我總是想知道數據庫在它暴露給消費者的周邊(表格/視圖或特效)時能夠保證的服務/完整性。爲了減輕它不作爲聲明性約束,你可以有一個每小時/每天的過程,檢查潛在的問題,並將它們扼殺在萌芽狀態。使用數據庫元數據編寫/編碼生成和保持更新將會相對容易,併爲您提供更好的信心。 –

+0

+1確切地說,「如果你不能在數據庫中執行它,任何事情都可能發生」:這是我需要擴展的想法。在我無法說服他們的情況下,運行cron來檢查數據也是一個不錯的主意,我會考慮這一點。 – lepe

1

引用你的問題:

...存儲與填充數值...

你沒有表現出數字數據,只是恰好包含數字的字符數據的任何實例。如果你說他們的OrderTotal列是char(10),那麼我會開始擔心。

只是把它當作字符數據,你會沒事的。我看不到任何業務或技術案例來更改數據庫(除非您開始接近完全重寫)。

關於性能......如果這是實際上擔心,那麼你很可能有更大的問題需要處理。 MySQL是快速和準確的。

-

寫一個函數的地方,將ZEROFILL用戶輸入ID的查詢的目的。使用此功能無處不在您需要接受用戶輸入。永遠不要使用數字數據類型來存儲你的數據(如果PHP,從來沒有使用+,總是使用.來連接,等等......)

請記住,這是沒有區別Item_Number = "SHIRT123"或任何其他您可能遇到的字符串ID。

以關心

+0

是的,還有其他字段(如OrderTotal),其中使用int ...沒有問題。數據庫本身很舊(可能是8歲),但是系統完全從零開始改寫,無論是web還是windows客戶端,系統還沒有啓動,所以還是有時間來提出一些改變,我主要關心的是數據完整性,並減少錯誤的可能性,因爲它會被數百個分支機構使用。 – lepe

+0

「只要把它當作字符數據,你就會好起來的,我不會看到任何改變數據庫的商業或技術案例」:問題在於我不是唯一的開發者,如果有人想檢查填充何時是一個數字),那麼你正在添加損壞的數據。正如Cade評論的那樣,如果可能的話,我想在數據庫中執行它(因爲數據在不同的客戶端被修改)。 – lepe