關系型數據庫設計指南

1. 前言

在自己獨立開發一個項目的過程中,我發現了一些以往寫小 Demo 從來沒有遇到過的問題。

最近在獨立制作一個全棧的通知管理平臺。一開始我沒有考慮太多,直接根據頭腦中零星的想法就開擼后端數據庫 model 和 API,用的是學了半成品的 MongoDb。

結果就是寫到后面在遇到復雜的數據庫依賴關系時,我感到崩潰。這才想起指導老師給我發了一篇計算機的論文,我便開始虛心研究。

做一個項目要經過這些過程:

  • 系統分析
    • 可行性分析
    • 用戶需求分析
    • 整體功能模塊分析
    • 技術分析
    • 系統流程分析
  • 系統設計
    • 系統功能模塊設計
    • 系統結構設計
    • 數據庫概念設計
      • 數據庫設計
      • 數據庫表設計
  • 系統實現
    • 功能模塊的實現
    • API 接口功能的實現
  • 系統測試
    • 黑盒和白盒測試
    • 測試環境與條件
    • 功能測試

敲代碼的時候思維很局限,總覺得完成了某一個單個功能就算成功。真到讓我獨立設計一個項目,我還真就難住了。這里就來講講我第一個遇到的問題,數據庫怎么設計?

本文用到的工具:

eraser.io

2. 構建實體

打開一額eraser.io文件,在左側寫入所有的實體Entity,例如:

  • 用戶
  • 班級
  • 通知

然后在canvas中添加一個Diagram as Code > Entity Relationship也就是E-R圖。

? 一個最佳實踐:總是從用戶表User-Table開始著手你的 E-R 圖設計。
這是因為,一切都是為了用戶用戶就是上帝。

從用戶表開始,并從用戶的注冊開始。

我們的用戶表可以是這樣:

User {id string pkusername string uniqueemail stringbio string
}

20250331011304

強調一點:業務邏輯永遠不要成為主鍵,例如這里除了id外所有的屬性皆是如此。

也許你不需要一個createdAt鍵,但一個很中肯的建議是添加它,總有一天你會需要它的,當你需要它的時候可不能后悔。

User {id string pkusername string uniqueemail stringbio stringcreatedAt timestamp
}

同樣的方法,添加班級、通知,完成后如下圖所示:

20250331013108

3. 構建關系

關系分為多種:

  • 一對一
  • 一對多
  • 多對多

這里用戶和班級之間存在多對多的關系,構建關系時我們也總遵循從User表開始的原則,正如之前提到的,用戶是整個產品的核心。

為了加深對關系的了解,這里舉個用戶發推文的例子:一個用戶能發多個推文,每一條推文只有一個用戶作為作者。這是一對多的關系,一個用戶對應多個推文,但每一條推文只能對應一個用戶。

在這里,假如我希望一個班級對應多條通知,在eraser.io中可以使用這樣的語法來表示:

# 一對多
Classes.id < Notifies.classId

這里用到的關系符號是<,同樣的還有一對一和多對多,分別用-<>符號表示數量關系。

觀察上面的代碼你會發現一個問題:通知實體并沒有classId這個鍵。

這就是我們需要創建的,這里classId是一個外鍵,表示引用了一個其他表的主鍵。

我們修改通知Entity的結構:

Notify {id string pktitle stringcontent stringcreatedAt timestampclassId string pk
}Class.id < Notify.classId

修改后大概是這樣:

pk

這里我們再添加一個Media實體:

Media {id string pkfileUrl stringtype enumcreatedAt timestamp
}

很顯然,一個班級對應多條通知,一條通知可能對應了多個媒體,所以媒體也需要一個類似的外鍵來唯一的引用一個它所對應的通知。

你有沒有想過為什么反過來不行,為什么不是通知的外鍵引用到媒體呢?
很顯然,通知對應多個媒體,一條外鍵是不夠的,而媒體只對應一個通知,一個外鍵就剛好。

添加完成后我們再來加上顏色和圖標就是這個效果:

20250331015205

關鍵其實還有語義化的功能,在看到這個外鍵后就知道通知與某個班級有關,媒體與某條通知相關。

在這種情況下外鍵是很有意義的。

如果我們的用戶能夠在每一條通知下進行評論,就需要一個Comments實體。很明顯他用外鍵和唯一的用戶關聯表示該用戶的評論。

20250331020311

在這里,用戶和評論是一對多的關系,通知和評論也是一對多的關系,所以你能看到在評論的身上有兩條外鍵分別拉到了用戶和通知身上。

根據同樣的一對多的原理,我們來制造一個like,也就是用戶對評論的點贊:

20250331021319

4. 多對多

根據上面的例子我們不難發現,要處理一對一、一對多的關系都能直接使用外鍵來處理。

但是多對多呢?

用戶的好友是一個多對多的關系,用戶可以有多個好友,很多人也可以加這個用戶作為好友。

我們的班級和用戶之間也是這樣的關系,班級可以有很多成員而成員也能加入很多班級。

對于多對多的關系我們一般新建一個表,例如,用戶好友的關系。

20250331022917

這里比較令人困惑,要仔細看看。

這張表實際上就是單獨跟蹤了誰關注了誰,有兩個字段:關注follow,粉絲follower

如果要查詢用戶的粉絲可以用select * from Friends where follow = user_id就能查詢到用戶的所有粉絲。

如果要查詢用戶的關注列表就是:select * from Friends where follower = user_id

5. 總結

關于數據庫的設計關鍵是將所有實體抽象出來,并理清楚實體之間的關系。

本次實驗🧪的鏈接:https://app.eraser.io/workspace/1GT4Nb82OR4LTYIuOmkT

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81251.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81251.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81251.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

詳解TypeScript中的類型斷言及其繞過類型檢查機制

TypeScript中的類型斷言及其繞過類型檢查機制 一、類型斷言的本質與工作原理編譯時與運行時的區別TypeScript編譯器處理類型斷言的步驟 二、類型斷言的詳細語法與進階用法基礎語法對比鏈式斷言斷言修飾符1. 非空斷言操作符 (!)代碼分析1. getLength 函數分析用法說明&#xff1…

XLSX.utils.sheet_to_json設置了blankrows:true,但無法獲取到開頭的空白行

在用sheetJs的XLSX庫做導入&#xff0c;遇到一個bug。如果開頭行是空白行的話&#xff0c;調用sheet_to_json轉數組獲得的數據也是沒有包含空白行的。這樣會導致在設置對應的起始行時&#xff0c;解析數據不生效。 目前是直接跳過了開頭的兩行空白行 正確應該獲得一下數據 問…

PostgreSQL 數據庫下載和安裝

官網&#xff1a; PostgreSQL: Downloads 推薦下載網站&#xff1a;EDB downloads postgresql 我選了 postgresql-15.12-1-windows-x64.exe 鼠標雙擊&#xff0c;開始安裝&#xff1a; 安裝路徑&#xff1a; Installation Directory: D:\Program Files\PostgreSQL\15 Serv…

一、Javaweb是什么?

1.1 客戶端與服務端 客戶端 &#xff1a;用于與用戶進行交互&#xff0c;接受用戶的輸入或操作&#xff0c;且展示服務器端的數據以及向服務器傳遞數據。 例如&#xff1a;手機app&#xff0c;微信小程序、瀏覽器… 服務端 &#xff1a;與客戶端進行交互&#xff0c;接受客戶…

奇偶ASCII值判斷

奇偶ASCII值判斷 Description 任意輸入一個字符&#xff0c;判斷其ASCII是否是奇數&#xff0c;若是&#xff0c;輸出YES&#xff0c;否則&#xff0c;輸出NO。例如&#xff0c;字符A的ASCII值是65&#xff0c;則輸出YES&#xff0c;若輸入字符B(ASCII值是66)&#xff0c;則輸…

OpenCV 圖形API(74)圖像與通道拼接函數-----合并三個單通道圖像(GMat)為一個多通道圖像的函數merge3()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 從3個單通道矩陣創建一個3通道矩陣。 此函數將多個矩陣合并以生成一個單一的多通道矩陣。即&#xff0c;輸出矩陣的每個元素將是輸入矩陣元素的…

多節點監測任務分配方法比較與分析

多監測節點任務分配方法是分布式系統、物聯網&#xff08;IoT&#xff09;、工業監測等領域的核心技術&#xff0c;其核心目標是在資源受限條件下高效分配任務&#xff0c;以優化系統性能。以下從方法分類、對比分析、應用場景選擇及挑戰等方面進行系統闡述&#xff1a; 圖1 多…

【推薦系統筆記】BPR損失函數公式

一、BPR損失函數公式 BPR 損失函數的核心公式如下&#xff1a; L BPR ? ∑ ( u , i , j ) ∈ D ln ? σ ( x ^ u i j ) λ ∣ ∣ Θ ∣ ∣ 2 L_{\text{BPR}} - \sum_{(u, i, j) \in D} \ln \sigma(\hat{x}_{uij}) \lambda ||\Theta||^2 LBPR??(u,i,j)∈D∑?lnσ(x^ui…

Java 核心--泛型枚舉

作者&#xff1a;IvanCodes 發布時間&#xff1a;2025年4月30日&#x1f913; 專欄&#xff1a;Java教程 各位 CSDN伙伴們&#xff0c;大家好&#xff01;&#x1f44b; 寫了那么多代碼&#xff0c;有沒有遇到過這樣的“驚喜”&#xff1a;滿心歡喜地從 ArrayList 里取出數據…

新能源行業供應鏈規劃及集成計劃報告(95頁PPT)(文末有下載方式)

資料解讀&#xff1a;《數字化供應鏈規劃及集成計劃現狀評估報告》 詳細資料請看本解讀文章的最后內容。 該報告圍繞新能源行業 XX 企業供應鏈展開&#xff0c;全面評估其現狀&#xff0c;剖析存在的問題&#xff0c;并提出改進方向和關鍵舉措&#xff0c;旨在提升供應鏈競爭力…

Centos 7 yum配置出現一下報錯:

One of the configured repositories failed (CentOS-$releaserver-Base), and yum doesnt have enough cached data to continue. At this point the only safe thing yum can do is fail. There are a few ways to work "fix" this: 1.解決CentOS Yum Repositor…

Redis 常見問題深度剖析與全方位解決方案指南

Redis 是一款廣泛使用的開源內存數據庫&#xff0c;在實際應用中常會遇到以下一些常見問題&#xff1a; 1.內存占用問題 問題描述&#xff1a;隨著數據量的不斷增加&#xff0c;Redis 占用的內存可能會超出預期&#xff0c;導致服務器內存不足&#xff0c;影響系統的穩定性和…

HOOK上癮思維模型——AI與思維模型【88】

一、定義 HOOK上癮思維模型是一種通過設計一系列的觸發&#xff08;Trigger&#xff09;、行動&#xff08;Action&#xff09;、獎勵&#xff08;Reward&#xff09;和投入&#xff08;Investment&#xff09;環節&#xff0c;來促使用戶形成習慣并持續使用產品或服務的思維框…

【playwright】內網離線部署playwright

背景&#xff1a;安裝好python3.9后&#xff0c;由于內網無法使用pip安裝playwright&#xff0c;多方收集資料&#xff0c;終于部署完成&#xff0c;現匯總如下&#xff1a; 1、playwright需要python3.7以上的版本&#xff0c;如果低于這個版本先要將python解釋器升級 2、在可…

Unity動態列表+UniTask異步數據請求

Unity動態列表UniTask異步數據請求 很久沒有寫東西了。最近有一個需求&#xff0c;在Unity項目里&#xff0c;有幾個比較長的列表&#xff0c;經歷了一翻優化&#xff0c;趁這幾日閑暇&#xff0c;記錄下來&#xff0c;給自己留個筆記&#xff0c;也送給有緣之人共同探討吧。 …

pandas讀取Excel數據(.xlsx和.xls)到treeview

對于.xls文件&#xff0c;xlrd可能更合適&#xff0c;但需要注意新版本的xlrd可能不支持xlsx&#xff0c;不過用戶可能同時需要處理兩種格式&#xff0c;所以可能需要結合openpyxl和xlrd&#xff1f;或者直接用pandas&#xff0c;因為它內部會處理這些依賴。 然后&#xff0c;…

2025年Jetpack Compose集成網絡請求庫的完整實施方案

Compose中集成網絡請求庫&#xff0c;網絡請求現在Retrofit是最流行的。 首先在Compose中如何進行網絡請求&#xff0c;而不僅僅是集成庫。因為Compose本身是UI框架&#xff0c;網絡請求其實還是通過ViewModel或者Repository來處理&#xff0c;然后通過狀態管理來更新UI。所以…

機器視覺開發-攝像頭掃描二維碼

以下是使用Python和OpenCV實現攝像頭掃描二維碼的最簡單示例&#xff1a; import cv2 from pyzbar import pyzbar# 打開攝像頭 cap cv2.VideoCapture(0)print("正在掃描二維碼... (按 q 鍵退出)")while True:# 讀取攝像頭幀ret, frame cap.read()if not ret:print…

Seata服務端回滾事務核心源碼解析

文章目錄 前言一、doGlobalRollback3.1、changeGlobalStatus3.2、doGlobalRollback 前言 本篇介紹Seata服務端接收到客戶端TM回滾請求&#xff0c;進行處理并且驅動所有的RM進行回滾的源碼。 一、doGlobalRollback doGlobalRollback是全局回滾的方法&#xff1a; ??首先依舊…

新聞客戶端案例的實現,使用axios獲取數據并渲染頁面,路由傳參(查詢參數,動態路由),使用keep-alive實現組件緩存

文章目錄 0.頁面要求1.功能要求2.開始路由配置2.1.嵌套二級路由如何配置?2.2.路由重定向,NotFound頁面,去除"#"號 3.實現底部導航欄的高亮效果4.渲染首頁:使用axios請求數據5.路由傳參5.1.回顧:查詢參數傳參或者動態路由傳參5.2.具體代碼 6.渲染詳情頁7.解決請求過程…