ข้ามไปยังเนื้อหา

ความสัมพันธ์มีผลตามมา

มีให้อ่านอีก 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 brick house with a glass room built onto its side, and a separate timber garden studio across the lawn, joined to it only by a stepping-stone path.
ภาพสร้างด้วย AI

โมดูลที่ 7 จาก 10 ในบท สถาปัตยกรรมข้อมูล Salesforce บทที่ 3 ของหลักสูตร Data Architect แต่ละโมดูลอ่านแยกกันได้ ก่อนหน้า: ฟิลด์ก็คือสถาปัตยกรรม · ถัดไป: ความเป็นเจ้าของและวงจรชีวิต

คำถามที่โมดูลนี้ตอบ: ฉันกำลังเลือกอะไรจริงๆ เมื่อเชื่อมออบเจกต์ Salesforce สองตัวเข้าด้วยกัน?

การวาดความสัมพันธ์นั้นง่าย ในบทที่ 2 เราวาดเส้นและตั้งชื่อมัน: พันธมิตรค้าปลีกส่งใบรายการสินค้าหลายใบ การจัดส่งหนึ่งรายการขนสินค้าหลายรายการ ทีมจัดส่งและรถบรรทุกมาพบกันในการมอบหมายทีม เราคุยเรื่อง cardinality ความเป็นทางเลือก และประวัติ ตอนนี้เรา implement เส้นเหล่านั้นบน Salesforce และเส้นบนไดอะแกรมก็เริ่มแบกน้ำหนักมากขึ้นมาก

เมื่อผมเลือกประเภทความสัมพันธ์บน Salesforce ผมไม่ได้แค่บอกว่า สองเรกคอร์ดนี้เชื่อมกัน ผมอาจกำลังตัดสินด้วยว่าใครเป็นเจ้าของลูก ลูกมีอยู่ได้โดยไม่มีแม่ไหม ใครเห็นมันได้ จะเกิดอะไรขึ้นเมื่อแม่ถูกลบ มันย้ายไปอยู่กับแม่ตัวอื่นได้ไหม ผมสรุปยอดมันขึ้นไปที่แม่ได้ไหม และจะเกิดอะไรขึ้นเมื่อมีลูกหลายแสนรายการ ความสัมพันธ์ไม่ใช่แค่เส้น มันแบกพฤติกรรม

ก่อนจะพูดถึง lookup หรือ master-detail ให้กลับไปที่ธุรกิจ ลองดูการจัดส่งกับรายการจัดส่งของมัน: ตู้เย็น การติดตั้ง การขนของเก่าทิ้ง รายการหนึ่งมีอยู่ได้โดยไม่มีการจัดส่งของมันไหม? ไม่ได้ ถ้าการจัดส่งถูกลบ รายการของมันควรถูกลบไปด้วยไหม? ควร รายการต้องการเจ้าของหรือความปลอดภัยของตัวเองไหม? ไม่จริง ควรมีใครย้ายรายการจากการจัดส่งหนึ่งไปอีกการจัดส่งไหม? หวังว่าจะไม่เกิดโดยบังเอิญ

ทีนี้ลองดูการจัดส่งกับเส้นทางที่มันอยู่ การจัดส่งมีอยู่ก่อนถูกจัดเส้นทาง ย้ายไปเส้นทางอื่นได้เมื่อแผนเปลี่ยน และการลบเส้นทางไม่ควรลบการจัดส่งบนนั้นเลย สองเส้นแบบหนึ่งต่อหลายที่ดูเหมือนกันบนไดอะแกรม แต่พฤติกรรมต่างกันโดยสิ้นเชิง สังเกตว่าเรายังไม่ได้พูดว่า “lookup” หรือ “master-detail” อธิบายพฤติกรรมก่อน การตั้งค่าจะ implement มัน

เปิดหน้าจอ New Field แล้ว Salesforce จะเสนอประเภทความสัมพันธ์ให้คุณจำนวนหนึ่ง (Object Relationships Overview (opens in a new tab) ภาษาอังกฤษ):

  • Lookup: เชื่อมสองออบเจกต์ เป็นข้าวปลาอาหารหลักของความสัมพันธ์ใน Salesforce
  • Master-detail: การผูกแม่กับลูก โดยแม่ควบคุมลูก
  • Many-to-many (หลายต่อหลาย): ไม่ใช่ประเภทฟิลด์ของตัวเอง แต่เป็นรูปแบบ: Junction Object ของ Salesforce (ออบเจกต์ที่กำหนดเองที่มีความสัมพันธ์ master-detail สองชุด)
  • Self-relationship (ความสัมพันธ์กับตัวเอง): lookup จากออบเจกต์หนึ่งไปหาตัวมันเอง
  • Hierarchical (ตามลำดับชั้น): lookup แบบพิเศษที่มีเฉพาะบนออบเจกต์ User เช่นผู้จัดการของผู้ใช้
  • External lookup และ indirect lookup: ความสัมพันธ์ไปและมาจากออบเจกต์ภายนอก คือออบเจกต์ __x จากโมดูลที่ 4 external lookup ชี้ไปที่ออบเจกต์ภายนอกที่เป็นแม่ ส่วน indirect lookup ชี้จากออบเจกต์ภายนอกไปยังออบเจกต์มาตรฐานหรือออบเจกต์ที่กำหนดเอง โดยจับคู่ตาม External ID ที่ไม่ซ้ำ

เวลาออกแบบส่วนใหญ่ของคุณจะหมดไปกับสามแบบแรก มาดูทีละแบบกัน

lookup บอกว่า: เรกคอร์ดนี้เกี่ยวข้องกับเรกคอร์ดนั้น ลูกเก็บตัวตน เจ้าของ และชีวิตของตัวเองไว้ การจัดส่งชี้ไปที่เส้นทางของมัน ถ้าเส้นทางถูกยกเลิก การจัดส่งไม่ได้หายไป มันกลับไปรอจัดเส้นทางใหม่

ตลกดี: ฟิลด์ lookup อยู่บนลูก แต่แม่ก็ได้อะไรบางอย่างด้วย คือรายการที่เกี่ยวข้อง (related list) ของลูกๆ ดังนั้นเมื่อคุณสร้างมัน ให้ตั้งชื่อทั้งสองปลาย Related List Label คือสิ่งที่คนเห็นบนแม่ และ Child Relationship Name คือสิ่งที่นักพัฒนาและการผสานรวมใช้เดินจากแม่ไปหาลูก อย่ายอมรับค่าเริ่มต้น

lookup เป็นแบบบังคับหรือไม่บังคับก็ได้ เมื่อไม่บังคับ คุณต้องตัดสินว่าจะเกิดอะไรขึ้นถ้าเรกคอร์ดที่มันชี้ไปถูกลบ และมีสามทางเลือก (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ):

  • Clear the value of this field (ล้างค่าฟิลด์นี้) ซึ่งเป็นค่าเริ่มต้น ลูกยังอยู่ โดยมี lookup ว่างเปล่า
  • Don’t allow deletion (ไม่อนุญาตให้ลบ) เรกคอร์ดที่ถูก lookup ลองลบเส้นทางดู แล้ว Salesforce จะปฏิเสธ: มันเป็นส่วนหนึ่งของความสัมพันธ์
  • Delete this record also (ลบเรกคอร์ดนี้ด้วย) คือการลบแบบต่อเนื่อง (cascade delete) เหมือน master-detail มีให้เลือกเฉพาะ lookup ที่กำหนดเองบนออบเจกต์ที่กำหนดเอง ปิดไว้โดยค่าเริ่มต้น และ Salesforce ต้องเป็นผู้เปิดให้ org ของคุณ เพราะการลบแบบต่อเนื่องข้ามความปลอดภัยและการแชร์: ผู้ใช้อาจลบเรกคอร์ดที่ตัวเองมองไม่เห็นด้วยซ้ำ

นั่นคือการตัดสินใจเรื่องวงจรชีวิตที่ซ่อนอยู่ในหน้าจอการตั้งค่า

Lookup filter (ตัวกรอง lookup) จำกัดสิ่งที่ผู้ใช้เลือกได้ สมมติว่าการจัดส่งมี lookup ชื่อ Installer ไปที่ผู้ติดต่อ และช่างติดตั้งเป็นประเภทเรกคอร์ดหนึ่งในผู้ติดต่อหลายประเภท ตัวกรอง lookup จะแสดงเฉพาะช่างติดตั้ง และกรองได้ตามเรกคอร์ดปัจจุบัน ตามเรกคอร์ดที่ถูก lookup และตามผู้ใช้: โปรไฟล์ บทบาท หรือสิทธิ์ของเขา (Lookup Filters (opens in a new tab) ภาษาอังกฤษ) เป็นวิธีราคาถูกที่ทำให้ lookup ซื่อตรง

master-detail ประกาศสิ่งที่หนักแน่นกว่ามาก ในคลาสผมเรียกมันว่าการผูกที่แน่นมาก คุณมี detail โดยไม่มี master ไม่ได้ ฟิลด์ master บังคับกรอก detail สูญเสียฟิลด์ Owner ของตัวเอง และสืบทอดเจ้าของของแม่ ไม่มี share table แยกสำหรับ detail คุณจึงแชร์ลูกแยกเดี่ยวไม่ได้ มันสืบทอดการแชร์ของแม่ นั่นคือเหตุผลที่ออบเจกต์ detail มีกฎการแชร์ การแชร์ด้วยตนเอง หรือคิวไม่ได้: ทั้งหมดต้องใช้ฟิลด์ Owner (Object Relationships Overview (opens in a new tab) ภาษาอังกฤษ) ในการตั้งค่า การตั้งค่าการแชร์ของมันจะแสดงว่า Controlled by Parent (ควบคุมโดยแม่) และบนฟิลด์ master-detail เอง คุณเลือก Sharing Setting: ผู้ใช้ต้องมีสิทธิ์ Read Only หรือ Read/Write บน master จึงจะสร้าง แก้ไข หรือลบ detail ของมันได้ การลบ master จะลบ detail ของมัน และ master ได้ฟิลด์สรุปยอด (roll-up summary)

ดังนั้นถ้ารายการจัดส่งเป็น detail ของการจัดส่ง ผมกำลังบอกว่า: รายการนี้เป็นของการจัดส่งนี้ตลอดชีวิต นั่นคือคำถามที่ผมอยากได้คำตอบก่อนที่ใครจะเลือก Master-Detail Relationship ใน Setup

นี่คือวิธีที่ผมชอบที่สุดในการรู้ว่าเราคิดถี่ถ้วนแล้วหรือยัง: จะเกิดอะไรขึ้นกับลูกถ้ามีคนลบแม่? ทุกคนเริ่มอึดอัด ดี ตอนนี้เรากำลังทำสถาปัตยกรรม

พันธมิตรค้าปลีกรายหนึ่งมีการจัดส่งในอดีตหลายแสนรายการ มีคนลบพันธมิตร การจัดส่งควรหายไปไหม? แทบแน่นอนว่าไม่: การเคลม การเรียกเก็บเงิน และประวัติล้วนพึ่งพามัน บางทีไม่ควรอนุญาตให้ลบพันธมิตรเลย และควรปิดการใช้งานพันธมิตรแทน ด้วย master-detail การลบ master จะลามไปยัง detail และ detail ของ detail การกู้คืน master จะนำพวกมันกลับมา (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ) ดังนั้นเมื่อมีคนพูดว่า “master-detail ให้ roll-up กับเรา” คำตอบของผมคือ: เยี่ยม แล้วคุณเพิ่งตกลงอะไรอีกบ้าง?

ด้วย lookup ลูกมีเจ้าของของตัวเองได้ ด้วย master-detail ไม่ได้ การเข้าถึงตาม master นั่นถูกต้องพอดีถ้า detail เป็นส่วนหนึ่งของแม่จริงๆ แต่ถ้าลูกต้องการเจ้าของของตัวเอง การแชร์ของตัวเอง หรือวงจรชีวิตของตัวเอง โมเดลกำลังบอกคุณว่า master-detail เป็นตัวเลือกที่ผิด โมดูลถัดไปลงลึกเรื่องความเป็นเจ้าของ และหลักสูตร Sharing and Visibility ไปไกลกว่านั้นอีก สำหรับตอนนี้: การออกแบบความสัมพันธ์และการออกแบบความปลอดภัยไม่ใช่การพูดคุยที่แยกกัน โมเดลข้อมูลกำหนดรูปโมเดลความปลอดภัยก่อนที่ใครจะเขียนกฎการแชร์

ลูกมีอยู่ได้ก่อนที่เราจะรู้ว่าแม่ของมันคือใครไหม? เรื่องนี้สำคัญกว่าที่ฟัง ถ้าการจัดส่งมาถึงในใบรายการสินค้าตั้งแต่คืนก่อน และเส้นทางถูกสร้างทีหลัง การบังคับให้มีเส้นทางบนการจัดส่งก็หมายความว่าต้องจัดเส้นทางก่อนจะสร้างเรกคอร์ดได้ด้วยซ้ำ ความสัมพันธ์เชิงกายภาพต้องรองรับวงจรชีวิตจริง ดังนั้นผมจึงไม่ออกแบบความสัมพันธ์จากไดอะแกรมนิ่งๆ อย่างเดียว ผมอยากรู้ว่า: มันเกิดอย่างไร อยู่เดี่ยวได้ไหม ย้ายได้ไหม และตายอย่างไร?

โดยค่าเริ่มต้น ลูกแบบ master-detail ย้ายไปอยู่กับแม่ตัวอื่นไม่ได้ คุณอนุญาตได้โดยเลือก Allow reparenting บนความสัมพันธ์ (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ) สัญชาตญาณของผมคือระมัดระวัง: ถ้าธุรกิจบอกว่าลูกเป็นของแม่ตัวเดียวตลอดชีวิต ผมไม่ทำให้การย้ายมันง่าย รายการที่ย้ายจากการจัดส่งหนึ่งไปอีกการจัดส่งควรเป็นเหตุการณ์ทางธุรกิจที่ตั้งใจ ไม่ใช่การแก้ไขฟิลด์ อีกครั้ง การตั้งค่าไม่ใช่สถาปัตยกรรม กฎของวงจรชีวิตต่างหากที่ใช่ และการตั้งค่า implement มัน

มีอีกสองเรื่องที่ทีมมักเจอทีหลัง คุณสร้างความสัมพันธ์ master-detail บนออบเจกต์ที่มีข้อมูลอยู่แล้วไม่ได้ คุณต้องสร้าง lookup กรอกค่าในทุกเรกคอร์ด แล้วจึงแปลง และคุณแปลงกลับเป็น lookup ได้ก็ต่อเมื่อไม่มีฟิลด์สรุปยอดบน master ระวังสิ่งที่การแปลงทำกับความปลอดภัยด้วย: การเปลี่ยน lookup เป็น master-detail จะตั้งการแชร์ของลูกเป็น Controlled by Parent และการเปลี่ยน master-detail กลับเป็น lookup จะตั้งค่าเริ่มต้นทั้งองค์กร (organization-wide default) ของลูกเป็น Public Read/Write (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ) เรกคอร์ดที่เมื่อวานเป็นส่วนตัว วันนี้เปิดโล่ง จนกว่าจะมีใครสังเกตเห็น เลือกตั้งแต่เนิ่นๆ

ผมชอบ roll-up นับรายการในการจัดส่ง รวมยอดเงินของบรรทัดในใบแจ้งหนี้ หาวันที่ล่าสุด: เป็นของในตัว ไม่ต้องเขียนโค้ด ฟิลด์ master-detail อยู่บนลูก แต่ roll-up อยู่บนแม่ แต่มันก็มาพร้อมตัวอักษรเล็ก (Roll-Up Summary Field (opens in a new tab) ภาษาอังกฤษ):

  • การคำนวณค่า roll-up หลังการเปลี่ยนแปลงบางอย่าง (ฟิลด์ roll-up ใหม่ สูตรที่มันพึ่งพาถูกเปลี่ยน การบังคับคำนวณใหม่) อาจใช้เวลาถึง 30 นาที ขึ้นกับจำนวนเรกคอร์ดที่ได้รับผลกระทบ ผมเคยเห็นคนสงสัยว่าทำไมตัวเลขบนแม่ยังไม่เปลี่ยน
  • มันสรุปทุกอย่างไม่ได้ Auto Number เป็นฟิลด์ที่ใช้รวมค่าไม่ได้ และ roll-up สรุปฟิลด์สูตรได้ก็ต่อเมื่อสูตรนั้นไม่เอื้อมข้ามไปยังออบเจกต์อื่น และไม่ใช้ฟังก์ชันที่เปลี่ยนค่าเอง เช่น NOW() หรือ TODAY() สูตร “จำนวนวันที่เกินกำหนด” ที่สร้างบน TODAY() เปลี่ยนค่าทุกคืนโดยไม่มีใครบันทึกเรกคอร์ด roll-up จึงไม่มีอะไรให้คำนวณใหม่ ตัวเลขแบบนั้นต้องใช้ scheduled flow หรือรายงาน
  • ตัวกรองก็มีข้อจำกัด: ใช้ฟิลด์ข้อความยาว multi-select picklist, Description ฟิลด์ระบบอย่าง Last Activity สูตรข้ามออบเจกต์ หรือฟิลด์ lookup ไม่ได้
  • roll-up ไม่อยู่บนหน้าแก้ไข กฎการตรวจสอบความถูกต้องจึงใช้มันได้ แต่แสดงข้อผิดพลาดตรงนั้นไม่ได้

และอย่ากลับลำดับการตัดสินใจ อย่าพูดว่า “เราต้องการ roll-up ดังนั้นนี่ต้องเป็น master-detail” ให้พูดว่า “ลูกนี้เป็นของแม่นี้จริงๆ ความเป็นเจ้าของและวงจรชีวิตเข้ากัน และหนึ่งในประโยชน์คือ roll-up ในตัว” ถ้าความหมายไม่เข้ากัน ให้แก้เรื่องการคำนวณด้วยวิธีอื่น อย่าบิดโมเดลข้อมูลเพื่อให้ได้ฟีเจอร์

แล้ววิธีอื่นคืออะไร? คุณสร้าง roll-up เอง: ฟิลด์บนแม่ที่เก็บค่าที่คำนวณแล้ว และระบบอัตโนมัติที่ทำให้มันเป็นปัจจุบันอยู่เสมอ สมมติว่าพันธมิตรค้าปลีกเป็น lookup จากการจัดส่ง อย่างที่ควรเป็น และธุรกิจต้องการ Open Deliveries (การจัดส่งที่ยังเปิดอยู่) บนพันธมิตร เพิ่มฟิลด์ตัวเลข Open Deliveries ให้พันธมิตร แล้วให้ record-triggered flow หรือ Apex trigger เมื่อปริมาณหรือตรรกะต้องใช้โค้ด คำนวณมันใหม่ทุกครั้งที่การจัดส่งเปลี่ยน มันทำงานข้าม lookup ได้ กรองตามอะไรก็ได้ และใช้วันที่และสูตรที่ roll-up ในตัวใช้ไม่ได้

แต่ตอนนี้การทำให้ถูกเป็นหน้าที่ของคุณ และนั่นคือจุดที่สิ่งเหล่านี้มักผิดพลาด ระบบอัตโนมัติต้องทำงานในทุกการเปลี่ยนแปลงที่สำคัญ: ลูกใหม่ ลูกที่ถูกแก้ไข ลูกที่ถูกลบ ลูกที่ถูกกู้คืน และลูกที่ย้ายไปอยู่กับแม่คนอื่น ซึ่งหมายถึงต้องคำนวณใหม่ทั้งแม่เก่าและแม่ใหม่ มันต้องรับการโหลดข้อมูลทีละ 200 เรกคอร์ดได้โดยไม่ชนขีดจำกัด นับใหม่ทั้งหมดแทนการบวกลบ เพื่อที่เหตุการณ์ที่หลุดไปครั้งเดียวจะไม่ทำให้ตัวเลขผิดไปตลอดกาล วางแผนวิธีคำนวณใหม่ทั้งหมด สำหรับการโหลดครั้งแรกและสำหรับวันที่ตัวเลขเพี้ยน และจำไว้ว่าการบันทึกลูกทุกครั้งตอนนี้จะอัปเดตแม่ด้วย แม่ที่มีลูกหลายพันรายการจึงนำปัญหาการล็อกที่เราจะได้เห็นในอีกสักครู่กลับมา roll-up ในตัวทำทั้งหมดนั้นให้คุณ ส่วน roll-up ที่สร้างเองคือซอฟต์แวร์ชิ้นเล็กๆ ที่คุณต้องดูแล

แพลตฟอร์มมีรูปร่างของมัน และ master-detail มีรูปร่างนั้นอยู่สองมิติ มิติแรกคือความลึก

คุณซ้อน master-detail ได้ลึกสามชั้น detail ที่กำหนดเอง และนั่นคือก้นบึ้ง (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ) ในคลาสผมวาดเป็นบัญชีที่มีคำสั่งซื้อ (หนึ่ง) คำสั่งซื้อที่มีรายการสินค้า (สอง) และรายการสินค้าที่มีรายละเอียด (สาม) แล้วผมก็ลองเพิ่มชั้นที่สี่ และ Salesforce ไม่ยอม ใน Steve Trucking อาจหน้าตาแบบนี้: การจัดส่ง (Delivery) คือ master รายการจัดส่ง (Delivery Item) ของมันคือชั้นแรก งานติดตั้ง (Install Task) ของรายการคือชั้นที่สอง และขั้นตอนงาน (Task Step) ของแต่ละงานคือชั้นที่สาม ชั้นที่สี่ เช่นบันทึกขั้นตอน (Step Note) ต้องเป็น lookup

master-detail สามชั้น ความสัมพันธ์แบบ master-detail สามชั้นที่ซ้อนกันใน Steve Trucking วาดเป็นเส้นหนา การจัดส่งคือ master รายการจัดส่งคือ detail ชั้นที่ 1 งานติดตั้งคือชั้นที่ 2 และขั้นตอนงานคือชั้นที่ 3 บันทึกขั้นตอนห้อยจากขั้นตอนงานด้วยเส้น lookup บางๆ เพราะชั้นที่สี่ต้องเป็น lookup ข้างใต้: ความเป็นเจ้าของ การแชร์ และการลบ ไหลลงจากการจัดส่งไปทุกชั้น ชั้นที่ 1 ชั้นที่ 2 ชั้นที่ 3 ชั้นที่สี่ต้องเป็น lookup การจัดส่ง Delivery__c · master รายการจัดส่ง Delivery_Item__c งานติดตั้ง Install_Task__c ขั้นตอนงาน Task_Step__c บันทึกขั้นตอน Step_Note__c ความเป็นเจ้าของ การแชร์ และการลบ ไหลลงจากการจัดส่งไปทุกชั้น หนึ่งพอดี ศูนย์หรือหนึ่ง หนึ่งหรือหลาย ศูนย์หรือหลาย master-detail lookup © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

การซ้อนมาพร้อมกฎสองสามข้อ:

  • ออบเจกต์มาตรฐานอยู่ฝั่ง detail ของออบเจกต์ที่กำหนดเองไม่ได้ ออบเจกต์ที่กำหนดเองเป็น detail ของบัญชีได้ แต่บัญชีเป็น detail ของออบเจกต์ของคุณไม่ได้
  • ออบเจกต์หนึ่งปรากฏได้เพียงครั้งเดียวในการซ้อนหลายชั้น Salesforce ไม่อยากให้คุณวนกลับมาที่ตัวเอง: subdetail เป็น master ของ master ของตัวเองไม่ได้
  • master ทำ roll-up จากชั้นล่างสุดโดยตรงไม่ได้ ถ้าการจัดส่งต้องการจำนวนขั้นตอนงาน งานติดตั้งต้อง roll-up ขั้นตอนของมัน รายการจัดส่งต้อง roll-up ค่า roll-up เหล่านั้น แล้วการจัดส่งจึง roll-up รายการ: ทีละชั้น
  • ความเป็นเจ้าของและการแชร์มาจากชั้นบนสุด ทุกชั้นสืบทอดเจ้าของและสิทธิ์เข้าถึงของ master
  • การลบ master จะลบทุกอย่างที่อยู่ใต้มัน และการกู้คืนมันก็นำทุกอย่างกลับมา

สามชั้นมักเพียงพอแล้ว ถ้าการออกแบบของคุณอยากได้ชั้นที่สี่อยู่เรื่อยๆ ให้ถามว่าทุกชั้นเป็นของชั้นที่อยู่เหนือมันไปตลอดชีวิตจริงหรือ และจำไว้ว่าคุณเลือกได้ว่าจะให้ลิงก์ไหนตัดสายโซ่ ชั้นที่สี่ไม่จำเป็นต้องเป็น lookup: บางทีงานติดตั้งอาจไม่ได้เป็นของรายการจัดส่งจริงๆ มันถูกจัดตารางและมอบหมายเป็นของตัวเอง ลิงก์นั้นจึงกลายเป็น lookup และตอนนี้งานติดตั้งก็เริ่มสายโซ่ใหม่ โดยมีขั้นตอนงานและบันทึกขั้นตอนอยู่ใต้มัน เลือกลิงก์ที่ลูกมีชีวิตของตัวเองจริงๆ แล้วให้ลิงก์นั้นเป็น lookup

ตัดสายโซ่ด้วย lookup ออบเจกต์ห้าตัวเดิมของ Steve Trucking เหมือนในแบบซ้อนสามชั้น แต่มี lookup อยู่ตรงกลาง การจัดส่งเป็น master โดยมีรายการจัดส่งเป็น detail บนเส้น master-detail หนา รายการจัดส่งลิงก์ไปที่งานติดตั้งด้วยเส้น lookup บางๆ ที่ตัดสายโซ่ งานติดตั้งเป็น master ใหม่: ขั้นตอนงานเป็น detail ของมัน และบันทึกขั้นตอนเป็น detail ของขั้นตอนงาน ทั้งคู่อยู่บนเส้น master-detail หนา ข้างใต้: ตอนนี้งานติดตั้งมีเจ้าของและการแชร์ของตัวเอง และการลบการจัดส่งไม่ลบงานติดตั้งของมันอีกต่อไป ชั้นที่ 1 lookup ตัดสายโซ่ ชั้นที่ 1 ชั้นที่ 2 การจัดส่ง Delivery__c · master รายการจัดส่ง Delivery_Item__c งานติดตั้ง Install_Task__c · master ใหม่ ขั้นตอนงาน Task_Step__c บันทึกขั้นตอน Step_Note__c ตอนนี้งานติดตั้งมีเจ้าของและการแชร์ของตัวเอง และการลบการจัดส่งไม่ลบงานติดตั้งของมันอีกต่อไป หนึ่งพอดี ศูนย์หรือหนึ่ง หนึ่งหรือหลาย ศูนย์หรือหลาย master-detail lookup © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

ตอนนี้งานติดตั้งมีเจ้าของและการแชร์ของตัวเอง การจัดส่งถูกลบได้โดยไม่พางานติดตั้งไปด้วย และงานติดตั้งมีชั้นอยู่ใต้มันได้อีกสองชั้น นั่นคือการแลกเปลี่ยน: สายโซ่สั้นลง และชีวิตของงานติดตั้งเป็นของมันเอง

ก่อนอื่น ขอพูดเรื่องคำศัพท์สักหน่อย เพราะ “junction object” มีสองความหมาย และผมสอนทั้งสองอย่าง

ในบทที่ 2 เราพบออบเจกต์เชื่อมเชิงตรรกะ (logical junction object): จุดเชื่อมของสองแนวคิดหลักที่กลายเป็นสิ่งของตัวเอง มีแอตทริบิวต์ของตัวเอง สุนัขตัวหนึ่งรู้หลายท่า ท่าหนึ่งเป็นที่รู้จักของสุนัขหลายตัว และท่าของสุนัขอยู่ระหว่างทั้งสอง ถือระดับทักษะและวันที่ไว้ นั่นคือออบเจกต์เชื่อมเชิงตรรกะ ในโมเดลเชิงตรรกะ นานก่อนที่ใครจะตัดสินว่าเป็น lookup หรือ master-detail

Salesforce ใช้คำนี้ในความหมายที่แคบกว่า เมื่อ Salesforce พูดว่า junction object มันหมายถึงออบเจกต์ที่กำหนดเองที่มีความสัมพันธ์ master-detail สองชุด (Create a Many-to-Many Object Relationship (opens in a new tab) ภาษาอังกฤษ) ผมจะเรียกมันว่า Junction Object ของ Salesforce ทุก Junction Object ของ Salesforce เป็นออบเจกต์เชื่อมเชิงตรรกะ แต่ไม่ใช่ทุกออบเจกต์เชื่อมเชิงตรรกะจะกลายเป็น Junction Object ของ Salesforce: สร้างมันด้วย master-detail หนึ่งชุดกับ lookup หนึ่งชุด หรือ lookup สองชุด มันก็ยังเป็นออบเจกต์เชื่อมเชิงตรรกะ แค่ไม่ใช่แบบของ Salesforce (Salesforce เองก็ไม่ได้สม่ำเสมอเสียทีเดียว: เอกสารอ้างอิงออบเจกต์ของมันเรียกออบเจกต์มาตรฐานบางตัวที่สร้างบน lookup ว่า “junction object” ในข้อสอบ ให้ถือตามนิยามแบบแคบ)

ความรู้ที่ออกสอบ Junction Object ของ Salesforce คือออบเจกต์ที่กำหนดเองที่มีความสัมพันธ์ master-detail สองชุด และนั่นคือสิ่งที่ Salesforce หมายถึงเมื่อพูดว่า “junction object” ส่วนออบเจกต์เชื่อมเชิงตรรกะคือแนวคิดการสร้างโมเดลที่กว้างกว่า: ออบเจกต์ใดก็ตามที่เชื่อมอีกสองตัวในความสัมพันธ์หลายต่อหลายและมีแอตทริบิวต์ของตัวเอง ไม่ว่าจะสร้างแบบไหน

มิติที่สองคือความกว้าง ลูกหนึ่งตัวมีแม่แบบ master-detail สองตัวได้ไหม? ได้ สามตัวล่ะ? ไม่ได้ ออบเจกต์ที่กำหนดเองแต่ละตัวมีความสัมพันธ์ master-detail ได้ไม่เกินสองชุด (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ) แม่แบบ master-detail สองตัวคือวิธีที่คุณสร้าง Junction Object ของ Salesforce สำหรับความสัมพันธ์หลายต่อหลาย ทีมจัดส่งและรถบรรทุกมาพบกันในการมอบหมายทีม (Crew Assignment) และอย่างที่เราพบในบทที่ 2 มันไม่ใช่แค่ท่อเชื่อม: มันมีวันที่ เส้นทาง และอาจมีสถานะ junction คือที่ที่ความสัมพันธ์กลายเป็นแนวคิดทางธุรกิจ เคล็ดลับของ Salesforce ในการสร้างมัน: ตั้งชื่อที่บอกว่ามันคืออะไร ให้ชื่อเรกคอร์ดเป็น Auto Number และเปลี่ยนชื่อรายการที่เกี่ยวข้องของแต่ละ master ให้เป็นชื่อของ master อีกตัว หน้าทีมจัดส่งจึงแสดง “Trucks” และหน้ารถบรรทุกแสดง “Crews” (Create a Many-to-Many Object Relationship (opens in a new tab) ภาษาอังกฤษ)

ความซับซ้อนอยู่ตรงนี้ แม่หนึ่งในสองตัวเป็นตัวหลัก (primary) และคือตัวที่ฟิลด์ master-detail ของมันถูกสร้างก่อน ไม่มีอะไรบนหน้าจอบอกว่าเป็นตัวไหน มันจึงเป็นคำถามข้อสอบคลาสสิก และเป็นเรื่องเซอร์ไพรส์คลาสสิกด้วย

ตัวหลักตัดสินอะไร? สามอย่าง (Create a Many-to-Many Object Relationship (opens in a new tab) ภาษาอังกฤษ):

  • หน้าตา หน้าของ junction ใช้สีและไอคอนของ master ตัวหลัก
  • เจ้าของ เรกคอร์ด junction สืบทอดเจ้าของของเรกคอร์ด master ตัวหลัก คุณไม่เคยเห็นมัน เพราะ detail ไม่มีฟิลด์ Owner มันสำคัญก็ต่อเมื่อคุณลบความสัมพันธ์ master-detail ทั้งสองชุดทิ้งในภายหลัง
  • Division (แผนก) ถ้า org ของคุณใช้ division ก็แบบเดียวกัน

และอีกตัวคือตัวรอง (secondary) มันหมายถึงอะไร?

  • มันอยู่ในลำดับถัดไปที่จะเป็นตัวหลัก ลบฟิลด์ master-detail ตัวหลักหรือแปลงเป็น lookup แล้วตัวรองจะกลายเป็นตัวหลัก
  • มันกำหนดขอบเขตของรายงาน Salesforce ให้ประเภทรายงานคุณสองแบบ: “Primary master with junction object and secondary master” และ “Secondary master with junction object and primary master” master ที่อยู่ลำดับแรกเป็นตัวตัดสินว่ารายงานแสดงเรกคอร์ดไหนได้
  • มันมีน้ำหนักเท่ากันในเรื่องสิทธิ์เข้าถึง ผมพูดแบบนี้: ความเป็นเจ้าของมาจากตัวหลัก สิทธิ์เข้าถึงมาจากทั้งสองตัว และตัวที่เข้มงวดที่สุดชนะ junction ก็เหมือน detail ทั่วไป ไม่มี share table ของตัวเอง Salesforce ตรวจสิทธิ์เข้าถึงของผู้ใช้บนเรกคอร์ด master ทั้งสอง ผ่าน Sharing Setting บนฟิลด์ master-detail แต่ละฟิลด์ ถ้าทั้งสองตั้งเป็น Read/Write ผู้ใช้ต้องมี Read/Write ทั้งบนทีมจัดส่งและบนรถบรรทุก จึงจะแก้ไขการมอบหมายทีมได้ (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ)
  • มันลบได้เท่ากัน ลบ master ตัวใดตัวหนึ่ง ทีมจัดส่งหรือรถบรรทุก แล้วเรกคอร์ด junction ของมันจะไปอยู่ในถังรีไซเคิล ลบทั้งสองตัว แล้วมันจะหายไปถาวร
ตัวหลักและตัวรองของ junction ออบเจกต์เชื่อม (junction object) อยู่ใต้แม่แบบ master-detail สองตัว วาดด้วยเส้นหนา ทีมจัดส่ง ซึ่งอยู่ด้านบนซ้าย เป็นตัวหลัก เพราะฟิลด์ master-detail ของมันถูกสร้างก่อน มันให้เจ้าของและหน้าตาแก่การมอบหมายทีม รถบรรทุก ซึ่งอยู่ด้านบนขวา เป็นตัวรอง มันกำหนดขอบเขตของประเภทรายงานแบบที่สอง และจะกลายเป็นตัวหลักถ้าความสัมพันธ์แรกถูกลบออก การมอบหมายทีมอยู่ระหว่างและใต้ทั้งสองตัว ข้างใต้: สิทธิ์เข้าถึงต้องผ่านแม่ทั้งสอง และตัวที่เข้มงวดที่สุดชนะ ลบแม่ตัวใดตัวหนึ่ง การมอบหมายก็หายไปด้วย เจ้าของ และหน้าตา ขอบเขต รายงาน ทีมจัดส่ง Crew__c · ตัวหลัก: สร้างก่อน รถบรรทุก Truck__c · ตัวรอง การมอบหมายทีม Crew_Assignment__c สิทธิ์เข้าถึงต้องผ่านแม่ทั้งสอง: ตัวที่เข้มงวดที่สุดชนะ ลบแม่ตัวใดตัวหนึ่ง การมอบหมายก็หายไปด้วย หนึ่งพอดี ศูนย์หรือหนึ่ง หนึ่งหรือหลาย ศูนย์หรือหลาย master-detail © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

กฎอีกสองสามข้อ: master ทั้งสองมี roll-up summary จาก junction ได้ และสูตรกับกฎการตรวจสอบความถูกต้องของ junction เอื้อมไปถึงฟิลด์บน master ทั้งสองได้ แต่ junction เป็น master ของสิ่งอื่นไม่ได้ มันจึงอยู่ตรงกลางของการซ้อนไม่ได้ และ master ทั้งสองเป็นออบเจกต์เดียวกันไม่ได้ ความสัมพันธ์หลายต่อหลายจากออบเจกต์หนึ่งไปหาตัวมันเองต้องใช้การออกแบบแบบอื่น และถ้าแม่ตัวหนึ่งมีเรกคอร์ด junction มากกว่า 200 รายการ และ junction ทำ roll-up ไปยังแม่อีกตัว Salesforce จะไม่ให้คุณลบแม่ตัวนั้นจนกว่าคุณจะลบเรกคอร์ดเหล่านั้นออกมากพอ

แล้วแม่ตัวไหนควรเป็นตัวหลัก? สร้างตัวที่เป็นเจ้าของความหมายก่อน สำหรับการมอบหมายทีม ทีมจัดส่งคือผู้ทำงาน ผมจึงสร้างทีมจัดส่งก่อน แล้วเขียนบันทึกไว้ เพราะไม่มีอะไรบนหน้าจอจะบอกคนถัดไป

พูดมาทั้งหมดนี้ ผมกลับไม่ค่อยได้ใช้ Junction Object ของ Salesforce มากนัก โดยทั่วไปออบเจกต์หนึ่งมีแม่แบบ master-detail ตัวเดียว และเป็นข้อมูลประเภทเดียวกัน: ข้อมูลลูกค้าใต้ข้อมูลลูกค้า ข้อมูลธุรกรรมใต้ข้อมูลธุรกรรม (จำประเภทข้อมูลในบทที่ 2 ได้ไหม: ข้อมูลลูกค้า ข้อมูลธุรกรรม ข้อมูลอ้างอิง) เมื่อแม่อีกตัวเป็นข้อมูลต่างประเภท ซึ่งมักเป็นออบเจกต์อ้างอิง ความสัมพันธ์นั้นจะเป็น lookup รายการจัดส่งเป็นของการจัดส่งของมัน: master-detail ทั้งคู่เป็นข้อมูลธุรกรรม มันชี้ไปที่ผลิตภัณฑ์ที่มันบรรทุกด้วย lookup เพราะผลิตภัณฑ์เป็นข้อมูลอ้างอิงที่มีชีวิตของตัวเอง และไม่มีใครอยากให้การลบผลิตภัณฑ์พาประวัติการจัดส่งหลายปีหายไปด้วย รายการจัดส่งยังคงเป็นออบเจกต์เชื่อมเชิงตรรกะระหว่างการจัดส่งกับผลิตภัณฑ์ที่อยู่บนมัน แค่ไม่ใช่ Junction Object ของ Salesforce

ออบเจกต์หนึ่งสัมพันธ์กับตัวเองได้: บัญชีแม่ ผู้จัดการ ศูนย์กระจายสินค้าที่รายงานต่อศูนย์ภูมิภาค Salesforce สร้างไว้ให้สองแบบที่คุณจะเจอแทบทุก org: บัญชีกับบัญชี คือฟิลด์ Parent Account ที่สร้างลำดับชั้นบัญชี และเคสกับเคส คือ Parent Case จากโมดูลที่ 2 ที่จัดกลุ่มเคสที่เกี่ยวข้องกัน ความสัมพันธ์กับตัวเองต้องเป็น lookup และเรกคอร์ดชี้หาตัวเองไม่ได้ แม้สองเรกคอร์ดจะชี้หากันได้ (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ) บนออบเจกต์ User มันเป็นประเภทพิเศษของตัวเอง คือความสัมพันธ์แบบ hierarchical (ตามลำดับชั้น) ใช้กับเรื่องอย่างผู้จัดการของผู้ใช้ กลไกนั้นง่าย การตั้งชื่อต่างหากที่สำคัญ lookup จากศูนย์กระจายสินค้าไปศูนย์กระจายสินค้าที่ชื่อ Distribution_Center__c ไม่ช่วยใครเลย แม่? สำรอง? รับส่วนเกิน? ตั้งชื่อความสัมพันธ์ตามบทบาท ไม่ใช่ตามออบเจกต์ที่มันชี้ไป

ความสัมพันธ์กับตัวเอง ออบเจกต์สามตัว แต่ละตัวมี lookup ชี้หาตัวเอง บัญชีชี้ไปที่บัญชีแม่ผ่านฟิลด์ ParentId ซึ่งสร้างลำดับชั้นของบัญชี เคสชี้ไปที่เคสแม่ผ่านฟิลด์ ParentId ศูนย์กระจายสินค้า ซึ่งเป็นออบเจกต์ที่กำหนดเอง ชี้ไปที่ศูนย์ภูมิภาคของมันผ่านฟิลด์ชื่อ Regional_Hub__c ข้างใต้: เป็น lookup เสมอ ไม่ชี้หาเรกคอร์ดเดียวกัน และตั้งชื่อตามบทบาทที่มันทำ บัญชีแม่ เคสแม่ ศูนย์ภูมิภาค บัญชี Account · ParentId เคส Case · ParentId ศูนย์กระจายสินค้า Distribution_Center__c · Regional_Hub__c เป็น lookup เสมอ ไม่ชี้หาเรกคอร์ดเดียวกัน และตั้งชื่อตามบทบาทที่มันทำ หนึ่งพอดี ศูนย์หรือหนึ่ง หนึ่งหรือหลาย ศูนย์หรือหลาย lookup © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

เรื่องนี้เล็ก และเป็นข้อเท็จจริงแบบที่ไม่ค่อยมีคนรู้และมีแค่หนึ่งเดียว ซึ่งผมคาดว่าข้อสอบจะหยิบมาใช้ Hierarchical เป็น lookup แบบพิเศษที่มีเฉพาะบนออบเจกต์ User มันเชื่อมผู้ใช้คนหนึ่งกับผู้ใช้อีกคน และ Salesforce ไม่ยอมให้สายโซ่วนกลับ: ผู้ใช้ชี้หาตัวเองไม่ได้ ทั้งโดยตรงและโดยอ้อม (Object Relationships Overview (opens in a new tab) ภาษาอังกฤษ) ถ้าผู้จัดการของ Maria คือ Dev ผู้จัดการของ Dev จะเป็น Maria ไม่ได้ หรือเป็นใครก็ตามที่รายงานขึ้นไปถึง Maria ก็ไม่ได้

นั่นคือความต่างจากความสัมพันธ์กับตัวเองข้างบน บนบัญชีหรือออบเจกต์ที่กำหนดเอง สองเรกคอร์ดชี้หากันได้ บน User ลำดับชั้นต้องคงเป็นลำดับชั้น และมันเป็นวิธีเดียวที่จะเชื่อม User กับ User: lookup ธรรมดาจาก User ไปหาตัวเองไม่มีให้เลือก

คุณมีอยู่แล้วหนึ่งตัว ฟิลด์มาตรฐาน Manager บน User เป็นความสัมพันธ์แบบ hierarchical และกระบวนการอนุมัติใช้มันได้: ส่งคำขอนี้ไปที่ผู้จัดการของผู้ยื่น คุณสร้างของตัวเองได้ด้วย เช่น Escalation Contact หรือ Backup Approver และการอนุมัติก็ส่งต่อตามมันได้แบบเดียวกัน (ApprovalProcess, Metadata API (opens in a new tab) ภาษาอังกฤษ) อย่าสับสนกับลำดับชั้นบทบาท ซึ่งเป็นตัวกำหนดสิทธิ์เข้าถึงเรกคอร์ด ฟิลด์ hierarchical เป็นแค่ความสัมพันธ์ระหว่างผู้ใช้ มันไม่ได้แชร์เรกคอร์ดใดเลย

ความรู้ที่ออกสอบ ความสัมพันธ์แบบ hierarchical มีเฉพาะบนออบเจกต์ User เช่นฟิลด์มาตรฐาน Manager และผู้ใช้ชี้หาตัวเองไม่ได้ ทั้งโดยตรงและโดยอ้อม มันไม่ใช่ลำดับชั้นบทบาท

แต่ละออบเจกต์มีความสัมพันธ์ master-detail ได้สูงสุดสองตัว ฟิลด์ lookup และ master-detail รวมกันนับเป็นฟิลด์ความสัมพันธ์: ค่าเริ่มต้น 40 ต่อออบเจกต์ สูงสุด 50 เมื่อร้องขอ ฟิลด์สรุปยอด: ค่าเริ่มต้น 25 ต่อออบเจกต์ สูงสุด 40 (Increase the Maximum Relationships Allowed per Object (opens in a new tab); Increase the Maximum Limit of Roll-Up Summary Fields (opens in a new tab) ภาษาอังกฤษ) Salesforce เสริมว่าการเพิ่มข้อจำกัดใดข้อจำกัดหนึ่งอาจกระทบประสิทธิภาพ

คุณไม่จำเป็นต้องออกแบบตามตัวเลขเหล่านั้น แต่ต้องสังเกตเมื่อคุณเข้าใกล้มัน ออบเจกต์ที่มีความสัมพันธ์ห้อยอยู่ต่อกันไปเรื่อยๆ กำลังบอกอะไรคุณบางอย่าง บางทีมันเป็นศูนย์กลางขนาดนั้นจริงๆ หรือบางทีโมเดลผิด (และกฎเรื่องพื้นที่เผื่อของบทที่ 18 ใช้ได้: อยู่ให้ต่ำกว่าข้อจำกัดมากๆ โดยวัดที่ปีที่สาม)

แล้วก็มีแม่ที่มีลูกมากเกินไป แนวทางของ Salesforce เองคือไม่เกินราว 10,000 เรกคอร์ดลูกต่อแม่แบบ master-detail หนึ่งตัว (Considerations for Object Relationships (opens in a new tab) ภาษาอังกฤษ) และคู่มือเรื่องการเข้าถึงเรกคอร์ดในขนาดใหญ่ของพวกเขาก็พูดเช่นเดียวกันสำหรับความสัมพันธ์แม่-ลูกโดยทั่วไป (Parent-Child Data Skew (opens in a new tab) ภาษาอังกฤษ) เรกคอร์ดที่ 10,001 ไม่ได้ทำให้ org พัง แต่เลยจุดนั้นไป การบันทึกลูกอาจล็อกแม่ และการเปลี่ยนการแชร์บนแม่จะกระเพื่อมไปทุกลูก

ดังนั้นเมื่อผมเห็นแม่หนึ่งตัว ลูกจำนวนมหาศาล ผมถามว่า: ทำไมพวกมันทั้งหมดอยู่ใต้แม่เดียวกัน ใครเป็นเจ้าของ คิวรีมันอย่างไร และระบบอัตโนมัติอะไรแตะแม่? ทุกการจัดส่งภายใต้บัญชี “Steve Trucking” บัญชีเดียวจะเกิน 10,000 ในไม่กี่วัน ความสัมพันธ์หนึ่งต่อหลายที่ดูไร้พิษภัยกลายเป็นปัญหาข้อมูลกระจุกตัว (skew) โมดูลถัดไปแนะนำเรื่อง skew และส่วนที่ 2 จะลงลึก

นี่คือนิสัยที่ผมอยากได้จากโมดูลนี้ อย่าเริ่มจาก “ฉันต้องการ roll-up” “ฉันต้องการให้มันบังคับ” “ฉันอยากได้การแชร์ที่สืบทอด” นั่นเป็นเบาะแสของการ implement เริ่มจากธุรกิจ: ลูกมีชีวิตของตัวเองไหม ใครเป็นเจ้าของ มันอยู่เดี่ยวได้ไหม ย้ายได้ไหม จะเกิดอะไรขึ้นเมื่อแม่หายไป ความสัมพันธ์แบกข้อมูลไหม และแต่ละฝั่งใหญ่ได้แค่ไหน? แล้วเลือกความสัมพันธ์ที่ implement คำตอบเหล่านั้น

Lookup, master-detail หรือ junction? เมทริกซ์ของรูปแบบความสัมพันธ์สามแบบเทียบกับคำถามทางธุรกิจหกข้อ lookup: เรกคอร์ดลูกอยู่ได้ลำพัง มีเจ้าของเอง เปลี่ยนแม่ได้ และรับมือกับลูกมากกว่า 10,000 รายการต่อแม่ได้ แม้ยังต้องระวังข้อมูลกระจุกตัว (data skew) มันไม่ได้หายไปพร้อมแม่โดยค่าเริ่มต้น (ฟิลด์ถูกล้างค่า หรือการลบถูกบล็อก) และเก็บแม่ได้หนึ่งตัวต่อฟิลด์ มันหมายถึงเชื่อมกัน master-detail: ต้องมีแม่ ลูกรับเจ้าของของแม่มา ถูกลบแบบต่อเนื่องไปพร้อมแม่ เปลี่ยนแม่ได้เฉพาะเมื่ออนุญาตให้ reparenting และลูกมากกว่า 10,000 รายการทำให้เกิดการล็อกแม่และการคำนวณใหม่ มันหมายถึงเป็นของ Junction Object ของ Salesforce: ต้องมีแม่ทั้งสองตัว รับเจ้าของจากตัวหลัก ถูกลบไปพร้อมแม่ตัวใดก็ได้ และเป็นรูปแบบเดียวสำหรับหลายรายการทั้งสองฝั่ง มันหมายถึงแนวคิดทางธุรกิจ ข้างใต้: ตอบคำถามทางธุรกิจก่อน แล้วประเภทความสัมพันธ์จะตามมาเอง อยู่ได้ลำพัง มีเจ้าของเอง ไปพร้อมแม่ เปลี่ยนแม่ได้ หลายทั้งสองฝั่ง 10,000+ ต่อแม่ หมายถึง Lookup การจัดส่ง → เส้นทาง ล้างค่าหรือบล็อก โดยค่าเริ่มต้น แม่หนึ่งตัวต่อฟิลด์ ยังต้องระวัง skew เชื่อมกัน Master-detail การจัดส่ง → รายการจัดส่ง ต้องมีแม่ รับของแม่มา ลบแบบต่อเนื่อง เฉพาะเมื่อเปิด reparenting master หนึ่งตัวต่อฟิลด์ ล็อกแม่ คำนวณใหม่ เป็นของ Junction Object ของ Salesforce ทีมจัดส่ง + รถบรรทุก → การมอบหมายทีม ต้องมีแม่ทั้งสอง จากตัวหลัก แม่ตัวไหนก็ลบมันได้ เฉพาะเมื่อเปิด reparenting นั่นคือหน้าที่ของมัน แนวทาง 10,000 เดียวกัน แนวคิดทางธุรกิจ ตอบคำถามทางธุรกิจก่อน แล้วประเภทความสัมพันธ์จะตามมาเอง อย่าเริ่มจากฟีเจอร์ที่คุณอยากได้ © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

นอกเหนือจากการสอบ: AI เปลี่ยนอะไร AI เสนอความสัมพันธ์ได้ในไม่กี่วินาที แต่บอกคุณไม่ได้ว่าธุรกิจจะลบแม่ไหม การวาดไดอะแกรมที่เร็วขึ้นไม่ได้ทำให้ความสัมพันธ์ที่ผิดย้อนกลับได้ถูกลง เมื่อเรกคอร์ดหลายล้านและระบบอัตโนมัติหลายสิบตัวพึ่งพามันแล้ว

  • ลูกมีวงจรชีวิตของตัวเอง หรือเป็นของแม่จริงๆ และความเป็นเจ้าของกับการเข้าถึงควรเป็นของตัวเองหรือสืบทอดมา
  • ลูกมีอยู่ได้โดยไม่มีแม่ ย้ายระหว่างแม่ หรืออยู่รอดหลังแม่ถูกลบได้หรือไม่
  • lookup แต่ละตัวจะทำอะไรเมื่อแม่ถูกลบ: ล้างค่า ห้ามลบ หรือลบแบบต่อเนื่อง
  • ความสัมพันธ์แบบหลายต่อหลายเป็นแค่ท่อเชื่อม หรือเป็นแนวคิดทางธุรกิจ ออบเจกต์เชื่อมเชิงตรรกะจะกลายเป็น Junction Object ของ Salesforce หรือไม่ แม่ตัวไหนเป็นตัวหลัก และแม่ทั้งสองมีความหมายอย่างไรต่อสิทธิ์เข้าถึง
  • โมเดลเข้ากับรูปร่างของแพลตฟอร์มหรือไม่: ลึกสามชั้น detail ที่กำหนดเอง กว้างสองแม่แบบ master-detail ข้อจำกัดของความสัมพันธ์และ roll-up
  • จำนวนและการกระจายของลูกที่คาดไว้สร้างความเสี่ยงเรื่อง skew ที่ควรเปลี่ยนการออกแบบหรือไม่

ความสัมพันธ์คือชุดคำมั่นว่าข้อมูลสองชิ้นจะทำงานร่วมกันอย่างไร ให้คำมั่นอย่างตั้งใจ