我正在和一位開發人員討論應該使用默認值的問題。在這方面是否有一條硬性規定,還是最佳實踐中的灰色地帶?數據庫表應該有默認值嗎?
回答
我的規則:如果許多記錄將使用該默認值(至少在最初),那麼我喜歡使用它作爲默認值。例如,在線商店中的產品的圖像表可能有一個默認路徑images/NoPictureYet.png
。最終,這些將被替換,但對於圖片根本不存在的批量加載數據(也許大多數圖片根本不存在!),默認情況下(至少對我而言)是有意義的。
如果沒有合理的默認值(例如客戶數據庫中的「名字」 - 我不希望我的名字默認爲「名字」),那麼我將它設置爲非空和默認值 - 這是應用程序的確保輸入正確值的責任。
但沒有硬性規定。這一切都有所不同;)
我個人發現使用默認值的一個實際案例是last_modified
列。
此列絕不會被存儲過程或業務邏輯更新,而是在行中的任何值更改時通過觸發器自動更新。不過,它也默認設置爲GETDATE()
,這樣新行的值將包含創建時間的時間戳,基本上是上次修改時的時間戳。
ALTER TABLE users ADD CONSTRAINT dc_users_last_modified
DEFAULT GETDATE()
FOR last_modified;
更新觸發器會那麼像這樣的事情:
CREATE TRIGGER trigUpdate_users
ON users
FOR UPDATE
AS
BEGIN
IF NOT UPDATE(last_modified)
UPDATE users SET last_modified = GETDATE()
WHERE user_id IN (SELECT user_id FROM inserted);
END
GO
沒有硬性的規定可以適用。這取決於列。例如,默認的訂單類型可能是完全明智的,但客戶電話號碼默認的想法沒有意義。
它應該很簡單。如果數據通常對於每行都是唯一的,例如客戶電話號碼,或者默認值很可能隨時間而改變,那麼我不會使用它。這意味着它僅用於填充CreateDate,ModifiedDate或其他性質的列。
我會說它是一個灰色地帶。通常我不會設計一個具有很多默認值的新數據庫,但是在增強現有系統時通常需要使用它們。
例如將新的非空列添加到現有數據庫。您可能不希望(或能夠)更新插入到該表中的所有代碼,因此您需要在其上放置一個默認值以確保任何「遺留」代碼仍然可以插入數據(假設默認值是合適的對於遺留代碼當然)。
絕對是灰色區域。這是傳統數據庫問題的經典邏輯。
如果我們想成爲純粹主義者,並且說數據庫中沒有商業邏輯屬性,那麼答案將永遠不會使用它們。
實際上,我們可以像我們經常做的那樣做一個例外,並允許將缺省邏輯放入數據庫中。
如何愚蠢,必須在數據庫級別強制執行數據完整性,或者您沒有數據完整性。在應用程序中強制執行缺省值或約束或觸發邏輯最好是短視的。這幾乎是錯誤數據的保證,因爲數據庫經常在應用程序之外受到影響。 – HLGEM 2010-02-17 22:44:52
同意約束條件。但不是默認值,它不是數據完整性。 – ctrlShiftBryan 2010-02-18 03:00:18
如果該列必須有一個值(它不爲空),那麼缺省值很重要。事實上,如果您將列從允許空值更改爲不允許它們,則默認值非常必要,因爲並非所有現有代碼都可能會填充值。有時在這種情況下,默認值就像'UNKNOWN'。如果要使用WITH VALUES將缺省值提供給ALTER TABLE語句中的字段爲空的現有記錄(將列更改爲NOT NULL),那麼尤其如此。對於用戶字段,缺省值對於字段非常重要界面通常不會涉及。例如,我們在date_inserted和user_inserted列上有默認值,用戶甚至不知道它們在那裏。如果許多不同的應用程序可以填充數據以確保沒有人忘記這些列,這一點尤其重要。
然後有一些列在數據錄入時會給出一個值,以後可能會改變。像狀態欄這樣的東西。
許多列不能真正具有默認值。什麼是用戶的默認地址或名稱?
你所做的一個區別似乎取決於數據是真的「信息」還是隻是看家?用戶的電話號碼是關於有問題的實體(特定用戶)的一段數據。記錄添加或更改的時間不是。從某種意義上說,這些東西根本不是「信息」,更像審計線索。一種解決方案是將所有內務管理信息(內部和外部主鍵,添加時間和更改時間以及由誰發出,是否將記錄標記爲已刪除等)存儲在實際數據的單獨表格中。然後,您可以刪除數據並分發該更改。 – 2016-09-06 20:04:56
以下是我個人使用的關於默認值的指導原則,這些指導原則對我來說很好。在以下示例中,請考慮具有多個應用程序並具有對後端的讀/寫訪問權限的數據庫後端。在這些情況下,數據庫必須定義如何對數據進行建模,從而確保數據的完整性。
1)CreatedDate和ModifiedDate列。這些列通常會將getdate()(sql server)定義爲默認值。如其他帖子所述,這些字段可以隨後用觸發器等更新。
2)布爾狀態列。示例:「IsDefault」,「IsDeleted」(用於審計),「IsActive」等。所有這些字段通常都會有一個邏輯默認狀態,應該由數據模型來定義。對此的例外顯然是可空的三態布爾字段,其中null狀態表示關於存儲在記錄中的數據的某些內容。
3)數據約束定義:AllowNull = false且沒有默認定義的列。換句話說,應用程序需要一個值。
4)查找表外鍵標識:這可能不是常態,但對於很多查找表外鍵我將定義一個默認值,其中包含記錄的初始狀態。因此,例如,在「Event」表中,外鍵列「EventTypeId」(int-autoincrement)將具有默認值1並表示「常規」或其他內容。這將涵蓋大多數情況下,例如,我想記錄一個事件,但不關心特定的類型ID。
5)非關鍵字符串列:「Description」,「Comment」等。對於這些列,我通常將''默認定義爲簡化System.DbNull =>空應用程序中的空值轉換處理。這可能不適用於所有情況,特別是當有關表包含數百萬行並且存儲空間是問題時。
所以總之,使用默認值來確保存儲在數據庫中的實際數據的數據完整性。數據模型應該在其自身內定義這些數據完整性規則,並且任何與其交互的應用程序都將被強制遵守這些規則。另請注意,這不是教義,並且總會有例外。分別考慮每種情況,以便對您的數據庫/應用程序有意義。
tl; dr:默認值是業務邏輯,我希望在對象模型中使用業務邏輯。因此,數據庫不能包含默認值。
E.g.在數據庫中我有一個位域:IsANicePerson。此字段轉換爲Person類上的屬性。本質上樂觀,我想這個屬性的默認值是'真'。所以在Person類中我實現了這個(作爲isANicePerson後臺字段的默認值)。如果我會允許數據庫中的默認值,我將不得不復制這個邏輯。重複的代碼/邏輯是不好的。因此我反對默認值。
聲明:我住在OO世界並使用Linq2Sql。
- 1. 具有默認值的SQLite數據庫
- 2. MySQL列應該總是有默認值?
- 3. 空數據庫值和默認值
- 4. 我應該在數據中存儲默認行爲嗎?
- 5. 數據庫表中的鍵值應該散列嗎?
- 6. 更改SQL數據庫默認值
- 7. H2數據庫默認值TIMESTAMP列
- 8. SQL數據庫設計默認值
- 9. 數據庫架構,默認值是NOW()
- 10. activerecord:數據庫默認值不生效
- 11. 默認字段值到MySQL數據庫
- 12. 應該使用python庫默認安裝cli命令嗎?
- 13. 該數據庫表應該規範化嗎?
- 14. Oracle ODBC默認數據庫
- 15. MySQL的默認數據庫
- 16. Django的ORM的默認值不會應用到MySQL數據庫
- 17. 向MySQL數據庫中的表添加一列,默認值爲
- 18. 從數據庫返回值時創建默認列表項
- 19. SAP中列的數據庫表默認值
- 20. 具有默認值的Android Listview數據庫
- 21. 如何初始化具有默認值的數據庫
- 22. 只有傳遞給數據庫的默認值
- 23. 如何讓數據庫字段在OpenERP7中具有默認值?
- 24. 參數沒有默認值
- 25. Variant屬性可以有默認值嗎?
- 26. Spring數據JPA JpaRepository.save(實體)不返回數據庫默認值
- 27. 向sql-2012 express中的所有列,表,數據庫提供默認值
- 28. Combobox selecteditem如果默認的「所有」值應該是-1
- 29. 設置數據庫的默認值,如果值爲空
- 30. 實體應該映射到自己的數據庫表嗎?
不是真正意義上的「默認」。 – Andrew 2010-02-17 21:50:58
我更喜歡'created_date'和'modified_date'列的觸發器。 – FrustratedWithFormsDesigner 2010-02-17 21:52:20
@Daniel Vassallo:'modified_date'必須在更新時作爲觸發器完成,我喜歡'created_date'的代碼與'modified_date'一致。 ;)也許不是最好的理由,但是...哦! – FrustratedWithFormsDesigner 2010-02-17 22:00:00