開發軍規:mysql表欄位設計

開發軍規:mysql表字段設計

VARCHAR與CHAR如何選擇

參考:MySQL數據庫中CHAR與VARCHAR之爭 - 站長之家

總結:

使用VARCHAR理由

  1. 字段不經常更新

  2. 字段比較長,且長度不均(比如用戶留言,有的人長有的人短)

  3. 不用再檢索列

使用CHAR的理由

  1. 字段不是很長,且長度都比較均勻(比如用戶名)

  2. ……

多對多時一定要使用關聯表嗎

非得用關聯表時,才使用關聯表。

如果明確知道關聯數據不是很多,那就用一個大字段(text),用,分割ID就可以了。

但是如果這種關聯關係,是具有擴展性的,業務關係決定了關聯數據可能是無限多的(比如員工和公司的關聯,不能在員工或者公司行中使用一個大字段存一個員工的所有公司,或者一個公司所有的員工,這是不現實的),並且數據關聯性查詢比較頻繁,那麼就使用關聯表。

有複雜的查詢的,要用關聯表,不然很麻煩,in是 多個查單個,FIND_IN_SET是單個查 多個,但是遇到多個查多個就不好辦了(比如根據多個年級查課程,而課程關聯的也是多個年級),所以有複雜的查詢的一定要用關聯表。


條目表 和 json字段 的使用

不會再更改的信息,可以放在json字段中,否則的話,還是要用條目表。和不被查詢,即不與其它數據有關聯的,也可以用json字段

-- ------------------------------ Table structure for `fxz_dinne_card_mould_item`-- ----------------------------DROP TABLE IF EXISTS `fxz_dinne_card_mould_item`;CREATE TABLE `fxz_dinne_card_mould_item` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '對應套餐卡模板ID', `service_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '對應服務ID', `num` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '總次數', `price` decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '價值-用於和商家結算(指導價格)', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='套餐卡模板服務條目 表 (其實可以像訂單表一樣,無需這個表也可以)';-- ------------------------------ Table structure for `fxz_dinne_card_order`-- ----------------------------DROP TABLE IF EXISTS `fxz_dinne_card_order`;CREATE TABLE `fxz_dinne_card_order` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `user_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '用戶ID', -- 用這些信息為用戶生成訂單,這些信息,套餐卡模板可能會改變,但是改變不能夠影響用戶的訂單,所以這些信息必須此時固化到訂單信息中,仔細注意著點,這很重要! -- 不會再更改的信息,可以放在json字段中,否則的話,還是要用條目表 `dinne_info_json` text NULL COMMENT '套餐卡模板信息', `server_info_json` text NULL COMMENT '套餐卡模板服務條目信息', `create_time` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '創建時間', `pay_time` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '支付完成時間', `amount` decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '應付金額', `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '狀態,0-待支付,1-已支付', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='套餐卡訂單 表';

冗餘設計 與 業務邏輯

很多時候,冗餘設計可以讓業務邏輯更方便的實現

/* START ######################## 用戶可用卡信息 ######################## */ $cardServer = []; // 使用時,我們並不關心,是用了哪一張套餐卡,我們只管裡面的條目夠用就行,換句話說,套餐卡是可以跨卡使用的 $on = 'dinne_card_item.service_id = platform_service.id'; $cardServer = Model()->table('dinne_card_item,platform_service')->join('left')->on($on)->field('platform_service.id,platform_service.name,SUM(dinne_card_item.surplus) AS surplus')->where(['dinne_card_item.status' => 0, 'dinne_card_item.user_id' => $userInfo['member_id']])->group('dinne_card_item.service_id')->select();// 注意這裡的 SUM(dinne_card_item.surplus) AS surplus
-- ------------------------------ Table structure for `fxz_dinne_card_item`-- ----------------------------DROP TABLE IF EXISTS `fxz_dinne_card_item`;CREATE TABLE `fxz_dinne_card_item` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '對應套餐卡ID', -- 卡就是服務 `service_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '對應服務ID', `user_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '所屬用戶', `num` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '總次數', `use_num` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '已使用次數', -- 很多時候,冗餘設計可以讓業務邏輯更方便的實現 `surplus` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '剩餘次數', `update_time` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '最後更新(使用)時間', `price` decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '價值-用於和商家結算(指導價格)', `status` tinyint(4) unsigned NOT NULL DEFAULT 0 COMMENT '狀態,0-正常,1-已用完,2-已過期', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='套餐卡服務條目 表 套餐卡內包含的服務(只用於標準服務)'; 

要注意的一些問題

注意文本字段

 -- 文本的要設置為允許為空,因為它不能設置默認值(實際上默認值就是NULL),如果插入數據時沒有值會報錯的(沒有值時就用缺省值,而缺省值就是默認值) `content` longtext NULL COMMENT 'content', `pic` text NULL COMMENT '相冊,使用,分割多圖',

注意NULL和唯一索引問題

唯一索引不約束 null

 -- 這個用戶郵箱和手機是唯一的,但是有的人開始並沒有綁定郵箱或手機,所以也不能為空串,不然唯一衝突,所以只能允許為空null了,並且默認為null `email` char(32) NULL DEFAULT NULL COMMENT '用戶郵箱', …… UNIQUE KEY `email` (`email`) USING BTREE,

默認值問題

一定要為字段設置默認值,始終要設置默認值,除非是想面提到的文本字段不能設置默認值的情況

並且php中獲取參數,也要有默認值:

$request->param('status/d', 0)

不然獲取到的值可能為null,而數據庫字段NOT NULL那麼就會出錯。

請嚴格準守這些規則,任何時候,否則看這樣雖然起來不會有什問題,但是在生產環境中就會出現很多很多的問題。


數據庫名詞解析

數據庫是軟件,功能是提供存儲和查詢的服務,一般稱為存取服務。

數據庫軟件通常是以一個實例的方式呈現。

一個數據庫就是一個實例。

一個實例就是一個數據庫軟件。

一個實例上可以創建多個數據庫(這個數據庫不是上面提高的軟件的意思,而是業務數據庫)。

一個數據庫內有多張表。

一個實例可以有多個用戶賬號,這些賬號就是實例的管理用戶,也是連接賬號。


邊緣業務邏輯表

對於邊緣業務邏輯(臨時的需求),比如臨時的新功能(不是系統主功能,沒有也沒關係),記錄用戶有沒有查看過我們新的歡迎頁面(用cookie是不行的,用戶清除就又要看一次了),有沒有打開某個功能頁面等等這樣臨時的需求,可能只用那麼一兩次的業務。這種業務表可以使用臨時邊緣表來做。用 edgetem_ 做表前綴。


業務與字段 表設計經驗

訂單條目表,存商品的名稱,圖片,規格,是防止商品更改了。當時數據和以後數據可能不統一。

而一些關聯關係中,只存原始ID,這是說明,數據統一性比較強,數據從原始數據處獲取,原始數據更改了,所有地方都不一樣,統一了數據,這種有時候要求,原始數據不能隨意經常更改,刪除,易造成業務不穩定(如需改變,請直接新增,儘量避免刪除和改動數據),這類數據往往是系統設置的一些信息。

用id統一性,如果不統一,那麼就會出現,洗車卡可以扣減打蠟的服務了,因為我們判斷用戶是否有這個服務對應的卡是按照服務id來的,如果不統一,後來系統服務名稱發生改變後,就會出現用戶卡和系統卡兩個地方名稱不一致的問題。


擴展信息表

防止一個表字段太多,有時可以拆分到另一個擴展信息表裡面去。


其它

ASCII 、UTF-8、Unicode都是個啥啊,為啥會亂碼啊?

整形不考慮編碼

58趕集的mysql軍規

不用外鍵,因為由程序業務保證約束更合理。這樣整個程序邏輯更清晰,而不是把邏輯分散到數據庫中了。

think-orm 數據庫操作還是都保持統一比較好。

58到家MySQL軍規升級版


分享到:


相關文章: