Skip to content

畫出關係

另有 28 種語言版本

English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · 简体中文 · Português (Portugal) · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Русский · Svenska · Dansk · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

A card model of a region from above: one distribution center joined by red threads to many small stores, and a second center with its own.
圖片由 AI 生成

第 2 個模組,共 6 個,屬於 Data Architect 課程第 2 章為含義建模資料。每個模組都可以單獨閱讀。 上一篇:聆聽名詞 · 下一篇:構建邏輯模型

**本模組回答的問題:**如何把候選實體變成一個概念資料模型?

名詞已經上了白板。現在我想了解的是方框之間的連線,因為一堆實體還不算真正的資料模型。很多含義就存在於關係之中。一個零售合作夥伴運營著若干配送中心。一份裝貨清單列出若干配送。一次配送送達一位收貨人。一個配送小組駕駛一輛卡車。每一句陳述都告訴我關於業務的一些東西,每一句也都給了我另一個要問的問題。

我仍然不想談 Salesforce。我不是在問這應該是查閱關係還是主要-詳細資料關係,不是在考慮 Salesforce 交叉物件(Junction Object),也不是在決定父記錄被刪除時會發生什麼。我是在努力理解業務上的關係。

拿**「一個零售合作夥伴運營著若干配送中心」**來說。聽起來很簡單。但一個零售合作夥伴有一個配送中心還是多個?在 Steve Trucking,每個零售合作夥伴在 Steve Trucking 服務的每個區域都運營著一個區域配送中心,所以是多個。一個配送中心可以屬於多個零售合作夥伴嗎?配送中心本身是否重要,有自己的員工和歷史,還是隻是一個地址?如果某個零售合作夥伴離開了,我們還在意它的配送中心嗎?

這些不是 Salesforce 問題,而是業務問題,而答案可能徹底改變模型。

在深入之前,我想先給你一套從現在起每張圖都會用到的語言。它很小。兩個方框之間的一條線表示這兩樣東西相關,線兩端的標記表示有多少。

從一條普通的線開始,沒有任何標記。這是我在白板上的起點:我知道這兩個名詞相關,只是還沒問怎麼相關。然後線的兩端加上標記。橫穿線條的一道短豎線,也就是那個十字,表示一。鴉爪,也就是像鳥爪一樣分成三叉的那一端,表示多。在本模組後面,你會看到第一個標記旁邊出現第二個標記,一道豎線或一個圓圈,它回答的是另一個問題:可以沒有嗎?

要記住的唯一規則:**每個標記都在它所接觸的方框那一端來讀。**離方框最近的標記表示最多可以有多少;往外的下一個標記表示最少有多少。

讀懂連線 本課程圖形語言的圖例。沒有標記的普通線表示兩樣東西相關,但多少個還沒決定。端點上一道豎線表示一;鴉爪表示多。加上表示可選性的第二個標記:兩道豎線表示恰好一個;圓圈加豎線表示零個或一個;豎線加鴉爪表示一個或多個;圓圈加鴉爪表示零個或多個。每個標記都在它所接觸的方框處讀。 起點:一條普通的線 一條普通的線 這兩者相關;多少個還沒決定 接著:一或多 一 一道豎線(十字):所接觸方框的一個 多 鴉爪:所接觸方框的多個 然後:可以是零嗎? 恰好一個 兩道豎線:至少一個,至多一個 零個或一個 一個圓圈,再一道豎線:可能還不存在 一個或多個 一道豎線,再一個鴉爪:至少一個 零個或多個 一個圓圈,再一個鴉爪:沒有也可以 每一端都在它所接觸的方框處讀:離方框最近的標記是最多可以有多少;往外的下一個標記是最少。 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

在講 Steve Trucking 之前,先回到模組 1 裡的狗。我們有五個方框:主人、繁育者、狗、品種和技能。現在我要問它們之間的連線。

**一個還是多個?**一位主人可以有不止一隻狗;Ana 就有兩隻。一隻狗只有一位主人,至少在我們的模型裡是這樣。這就是一對多:主人一端畫一道豎線,狗一端畫鴉爪。繁育者也是同樣的形狀:一個繁育者繁育很多隻狗。

**可以沒有嗎?**Max 來自收容所,所以他根本沒有繁育者。繁育者一端加一個圓圈:一隻狗有零個或一個繁育者。不過每隻狗都有主人,所以那一端再加一道豎線:恰好一個。

**多對多?**一隻狗會很多項技能,而一項技能,比如坐下,有很多隻狗會。這就是多對多,而這正是我去尋找隱藏概念的地方。關於這隻狗會這項技能,有沒有什麼要說的?她做得有多好,什麼時候學會的。這個關係有它自己的事實,所以它成了一個獨立的事物:狗狗技能(Dog Trick),狗的名字放在前面,因為驅動它的是狗。

**每條線是什麼意思?**主人擁有一隻狗。繁育者繁育它。一隻狗會它的技能。給連線起好名字,任何人都能把模型讀回給你聽。

現在,還是隨時間變化?有沒有人在意 Bella 今天坐下做得有多好,或者她是怎麼練到這一步的?如果訓練師每隔幾個月檢查她一次,每次檢查就是一條獨立的記錄:一條技能評估(Trick Assessment),帶有日期、熟練程度和檢查人,歸屬於它所屬的那條狗狗技能。即使是一個已經變成事物的關係,也可以有它自己的歷史。

品種我暫時不連線。它仍然是模組 1 留下的那個問題:是一個獨立的方框,還是狗身上的一個詞,模組 4 會解決它。

帶有關係的狗狗模型 七個方框。一位主人擁有一隻或多隻狗,每隻狗恰好有一位主人。一個繁育者繁育一隻或多隻狗,一隻狗有零個或一個繁育者。一隻狗會零項或多項狗狗技能,一項技能見於零項或多項狗狗技能;每項狗狗技能對應一隻狗和一項技能。每項狗狗技能受檢於零次或多次技能評估。品種單獨存在,尚未連線。 擁有 繁育 會 見於 受檢於 主人 繁育者 狗 品種 狗狗技能 技能 技能評估 恰好一個 零個或一個 一個或多個 零個或多個 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

這些問題中的每一個,放到真實的業務上都同樣適用。現在我們拿它們來問 Steve Trucking。

關於一個關係,我最先想了解的事情之一是它的基數。這是資料庫術語;問題本身要簡單得多:**這邊的多少個可以與那邊的多少個相關?**在概念層次上,有三種基本模式。

這是整個過程中重要的一步:拿兩個不同的名詞,理解它們之間的關係。在大多數情況下,它是一對多或多對一。只有在少數情況下,你才會碰到一對一。

一對多無處不在。一個零售合作夥伴有多個配送中心。一份裝貨清單列出多次配送。一條路線有大約十個停靠點。聽到這樣的話,我就開始畫線。

現在這條線有了標記。每一端都說明它所接觸的方框有多少:豎線表示一,鴉爪表示多。從每個方框出發去讀:一個零售合作夥伴有多個配送中心。

基本連接線:一對多 兩組方框,每組用一條基本鴉爪表示法的連線相連。一個零售合作夥伴營運多個配送中心:零售合作夥伴一端是一道豎線,配送中心一端是鴉爪。一份裝貨清單列出多次配送,標記方式相同。每一端都配有文字說明。 一個零售合作夥伴 多個配送中心 營運 一個裝貨清單 多個配送 列出 零售合作夥伴 配送中心 裝貨清單 配送 一道豎線表示一。鴉爪表示多。每一端都從它所接觸的方框讀起。 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

一對一關係是存在的,但很少見,一旦發現,我會問一些問題。這真的是兩個不同的名詞,還是同一個?如果是不同的,它們之間的一對一關係是什麼?它會永遠是一對一,還是隻是現在一對一?這些都是設計資料模型時的關鍵問題。在任何一個早上,配送小組和卡車看起來都是一對一的:兩個人,一輛卡車,一條路線。但放到一個月裡看就不是了,而這個模型裡最有意思的關係正藏在那裡。

多對多關係特別有意思,因為它們常常告訴我們業務中還有另一個概念。一個配送小組會在一段時間裡開不止一輛卡車嗎?會。一輛卡車會由不止一個配送小組駕駛嗎?在它的整個使用期內,當然會。所以配送小組和卡車是多對多關係。但現在我想了解更多。業務方是否在意某個配送小組什麼時候開過某輛卡車?為哪條路線,在哪一天?是誰做的分配?如果關係本身承載著我們在意的資訊,我們就發現了另一個業務概念:配送小組分配(Crew Assignment)。

這是一個重要的建模習慣。有時最有意思的東西並不是我們最初聽到的某個名詞,而是藏在兩個名詞之間的關係裡。

這是我希望管理員開始換個角度思考的地方之一。在 Salesforce 裡,我們習慣談論物件和欄位,所以很容易把方框當成重要的部分,把連線當成管道。但關係本身可以有業務含義。

想想一次配送和它所載的產品。一次配送可以載好幾種產品,比如一臺洗衣機和一臺烘乾機。一種產品,比如同一型號的冰箱,會出現在成千上萬次配送中。這很簡單。但如果我需要知道這次配送裡有幾臺這種產品、是否要安裝、是否要把舊的拉走呢?我感興趣的就不再只是配送和產品之間的關係了。我感興趣的是一個配送項目(Delivery Item),而這個概念值得擁有自己的實體。

如果你有 Salesforce 背景,你可能已經在想:「這是個交叉物件。」你沒錯。但我不想從那裡開始。**配送項目先是一個業務概念,然後才是一個 Salesforce 交叉物件。**業務在先,實現在後。

對於這類關係實體,不管最後在哪裡構建,我都有幾個習慣。

給它起名字。如果業務方已經有一個詞,就用他們的。如果沒有,就把兩個父實體的名字拼在一起。想想訂單和產品。它們之間的東西是 Order Item(訂單項目):訂單,以及訂單上的項目。它同時是兩個父實體的子實體,在 Salesforce 裡最後可能成為一個 Salesforce 交叉物件。但哪個名字放在前面:Item Order,還是 Order Item?看看每個父實體是哪類資料。產品是參考資料;訂單是交易資料,而驅動它的是訂單。所以是 Order Item,或者 Order Product,就像 Salesforce 有 Opportunity Product(商機產品)一樣。在 Steve Trucking,它是配送項目(Delivery Item)。起驅動作用的名字放在前面,這樣在你將來看到的每一個清單裡,這條記錄都會排在它的所有者旁邊。

**給它自己的鍵。**人們很容易說配送項目由配送加產品來識別,然後就此打住。那是一個複合鍵,而複合鍵要難處理得多:每個指向這條記錄的系統都得帶著兩半。給關係實體一個自己的識別符號,把配送加產品作為一條關於唯一性的規則,而不是作為身分。

兩個父實體,一個子實體:給它自己的鍵 兩個父實體和一個子實體。配送(記錄 ID 為配送 ID;配送日期、狀態)包含多個配送項目。產品(記錄 ID 為產品 ID;名稱、型號編號)出現在多個配送項目上。配送項目位於兩者之間:它有自己的記錄 ID,即配送項目 ID,並帶有兩個父實體的配送 ID 和產品 ID,外加數量。下方的註記:配送 ID 加產品 ID 是一條關於唯一性的規則,而不是記錄 ID。 交易資料 參考資料 包含 出現在 配送 配送 ID 記錄 ID 配送日期 狀態 配送項目 配送項目 ID 記錄 ID 配送 ID 產品 ID 數量 產品 產品 ID 記錄 ID 名稱 型號編號 配送 ID + 產品 ID:一條關於唯一性的規則,而不是記錄 ID。 一個 多個 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

注意它上面沒有什麼:序列號。數量和序列號不屬於同一條記錄。數量統計的是某樣東西的若干件;序列號識別的是某一件特定的東西。如果業務需要序列號,每一件就成為自己的一條記錄,五臺冰箱就是五條記錄。我想不出有什麼理由讓配送項目下面再掛一個配送項目明細。要麼是這個,要麼是那個:帶數量的彙總,或者每件一條記錄。這裡用的是數量。

**留意想要歷史的屬性。**有些關係實體一旦建立就定下來了:這次配送裡的洗衣機,就一直是這次配送裡的洗衣機。另一些則不斷變化。一個配送小組這週開 117 號卡車,下週這輛卡車就歸了另一個小組。當關系會變化,而業務又在意它過去是什麼樣時,這個關係實體就需要日期,而配送小組分配正是需要留意的那一個。儘早問業務方在意的是現在還是隨時間變化;我們馬上會回到這個話題。

光說「一對多」不足以理解一個關係。我還想知道這個關係意味著什麼。

一次配送有一個地點。哪一個?它出發的配送中心?還是它送達的收貨人家裡?這兩者不能互換。兩個模型可以有完全相同的方框和完全相同的基數,而連線卻可以意味著完全不同的東西。這就是為什麼好的模型不只是用線連起來的方框。**連線需要名字。**如果我把圖交給另一位架構師,他們不應該需要去猜一個關係是什麼意思;如果我拿給業務方看,它應該使用他們認得的語言。

連線需要名字 兩個面板,每個面板裡都是地點方框在上、配送方框在下,用兩條連線相連,每條連線都標為一個地點對多次配送。左邊的面板「連線沒有名字」裡,兩條連線沒有標籤,看起來一模一樣。右邊的面板「有名字的連線」裡,一條連線標為「出發自」,另一條標為「送達」。方框相同,基數相同:只有名字能告訴你哪條連線是哪條。 連線沒有名字 有名字的連線 出發自 送達 地點 配送 地點 配送 方框相同,基數相同。只有名字能告訴你哪條連線是哪條。 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

「有多少?」裡還藏著另一個問題:這個關係是必需的嗎?一次配送能在被排上路線之前存在嗎?必須能:裝貨清單在配送前一兩天到達,而路線要到前一天晚上才最終確定。一次配送能在沒有零售合作夥伴的情況下存在嗎?不能;每一次配送都來自某個合作夥伴的裝貨清單。這就是可選性。

同樣,不要直接跳到 Salesforce 的必填核取方塊。說「每次配送都必須有一個零售合作夥伴」和說「Salesforce 應該在建立記錄時要求填寫零售合作夥伴欄位」是有區別的。它們最後可能是同一種實現,但不是同一句話。前者是一條業務規則;後者是執行它的一種方式。作為架構師,我們要先理解前者,再決定後者。

在圖上,可選性是每一端的第二個標記。離方框最近的標記表示最多可以有多少:豎線表示一,鴉爪表示多。往外的下一個標記表示最少有多少:又一道豎線表示至少一個,一個圓圈表示可以是零。所以每次配送都恰好在一份裝貨清單上,而一份裝貨清單列出一次或多次配送。一次配送位於零個或一個停靠點,在排上路線之前沒有停靠點,而一個停靠點卸下零次或多次配送。

讀懂每一端的兩個標記 一排三個方框:裝貨清單、配送、停靠點。一份裝貨清單列出一次或多次配送,每次配送恰好在一份裝貨清單上:裝貨清單一端是兩道豎線,配送一端是鴉爪和一道豎線。一個停靠點卸下零次或多次配送,每次配送位於零個或一個停靠點:配送一端是圓圈和鴉爪,停靠點一端是圓圈和一道豎線。離方框最近的是最多;往外的下一個標記是最少。 恰好一個裝貨清單 一個或多個配送 列出 零個或一個停靠點 零個或多個配送 卸下 裝貨清單 配送 停靠點 離方框最近:最多(一或多)。往外的下一個標記:最少(豎線是至少一個,圓圈是零)。 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

有一個問題我經常問:你說的是現在,還是隨時間變化?

一個配送小組駕駛一輛卡車。是現在嗎?是為了今天的路線嗎?還是在這兩個人共事的整個期間?這會產生不同的模型。如果業務方只在意一個小組今天開的是哪輛卡車,模型可以保持簡單。如果需要知道一個小組開過的每一輛卡車、什麼時候、在哪條路線上,我們就需要歷史,而我們發現的那個配送小組分配突然就變得非常重要了。

配送小組分配:哪個小組有哪輛卡車 兩個父實體和一個子實體。配送小組(記錄 ID 為配送小組 ID;名稱、狀態)承擔多項配送小組分配。卡車(記錄 ID 為卡車 ID,還以車輛編號為已知標識;品牌、型號、狀態)用於多項配送小組分配。每項配送小組分配都有自己的記錄 ID,並帶有配送小組 ID 和卡車 ID,沒有日期。下方的註記:哪個小組有哪輛卡車,但不知道從什麼時候開始。 承擔 用於 配送小組 配送小組 ID 記錄 ID 名稱 狀態 配送小組分配 配送小組分配 ID 記錄 ID 配送小組 ID 卡車 ID 卡車 卡車 ID 記錄 ID 車輛編號 又稱 品牌 型號 狀態 哪個小組有哪輛卡車,但不知道從什麼時候開始。 一個 多個 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

這是建模錯誤的一個常見來源。我們為當前狀態建模,因為那是我們在螢幕上能看到的。然後,幾週後,某個零售合作夥伴提出一起貨損索賠,有人問:「3 月 17 日是哪個小組開的 117 號卡車?」於是我們發現,每次分配變化時,我們都把答案覆蓋掉了。

保留這種歷史的一種方法,是讓分配成為一條獨立的記錄。給某個小組分配時,我們建立一條帶開始日期的配送小組分配。分配變化時,我們給舊記錄加上結束日期,再建立一條帶自己開始日期的新記錄。現在,「六個月前是誰負責那項分配?」就成了一個簡單的問題,而不需要去翻欄位歷史記錄或資料變更日誌。而一旦某個小組有過很多次分配,就會有人問哪一次是當前的,所以我還會加一個 Active(有效)標誌。

隨時間變化的配送小組分配:日期和 Active 標誌 兩個父實體和一個子實體,帶有日期。配送小組(記錄 ID 為配送小組 ID;名稱、狀態)承擔多項配送小組分配。卡車(記錄 ID 為卡車 ID,還以車輛編號為已知標識;品牌、型號、狀態)用於多項配送小組分配。每項配送小組分配都有自己的記錄 ID,並帶有配送小組 ID 和卡車 ID、開始日期、結束日期和一個 Active 標誌。下方的註記:每次變化都結束一項分配並開始下一項,Active 標出當前的那一項。 承擔 用於 配送小組 配送小組 ID 記錄 ID 名稱 狀態 配送小組分配 配送小組分配 ID 記錄 ID 配送小組 ID 卡車 ID 開始日期 結束日期 Active 卡車 卡車 ID 記錄 ID 車輛編號 又稱 品牌 型號 狀態 每次變化都結束一項分配並開始下一項。Active 標出當前的那一項。 一個 多個 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

所以,當有人告訴我一個關係時,我不只問這些東西如何相關。我會問:這個關係會變化嗎?我們在意它的歷史嗎?

我們的 Steve Trucking 模型正在變得有用。我們知道哪些關係是一對多,多對多關係在哪裡藏著另一個概念,哪些關係是可選的,哪些會隨時間變化。而我們仍然沒有建立任何 Salesforce 物件。這是有意的。

模組 1 和 2 之後的概念模型 Steve Trucking 的概念模型,按客戶資料、交易資料和參考資料分組。一個零售合作夥伴傳送列出多次配送的裝貨清單,並營運多個配送中心。每次配送從一個配送中心出發,送達一位收貨人,並包含多個配送項目。路線有多個停靠點,停靠點卸下配送。配送小組分配把一個配送小組和一輛卡車連到一條路線上,因此模型記下了誰在何時開哪輛卡車。 客戶資料 交易資料 參考資料 營運 傳送 列出 包含 出發自 送達 有 卸下 駕駛 承擔 用於 零售合作夥伴 我們為其配送的零售商 收貨人 收貨的人 裝貨清單 合作夥伴的配送清單 配送 一筆訂單送給一位收貨人 配送項目 卡車上裝的貨 路線 一天跑的停靠點 停靠點 路線上的一個地址 配送小組分配 誰在何時開哪輛卡車 配送中心 配送的出發地 配送小組 兩個人 卡車 車輛 恰好一個 零個或一個 一個或多個 零個或多個 © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

這張圖應該是我可以擺到業務方面前的東西,而且他們不需要了解 Salesforce 就能告訴我它對不對。如果因為圖裡滿是 Salesforce 術語而導致他們無法驗證,那我就過快地進入物理設計了。

在梳理概念模型中的關係時,我要決定的是:

  • 主要的業務實體彼此如何關聯。
  • 每個關係現在以及隨時間變化後,是一對一、一對多還是多對多。
  • 每個關係是必需的還是可選的。
  • 某個多對多關係是否藏著一個有意義的業務概念。
  • 關係是否隨時間變化,以及我們是否需要它的歷史。

查閱關係還是主要-詳細資料關係、交叉物件的配置、級聯行為和共用,這些都是物理層面的決定;我們會講到。現在我們仍在回答那個更重要的問題:這個業務實際上是如何運作的?一旦理解了實體以及它們之間的關係,我們就可以開始新增描述它們的細節。那時,我們的概念模型就開始變成一個邏輯資料模型了。