Przejdź do głównej zawartości

Relacje mają konsekwencje

Dostępne także w 28 językach

English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · 简体中文 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · 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.
Obraz wygenerowany przez AI

Moduł 7 z 10 w rozdziale Architektura danych Salesforce, rozdziale 3 kursu Data Architect. Każdy moduł jest samodzielny. Wstecz: Pola to też architektura · Dalej: Własność i cykl życia

Pytanie, na które odpowiada ten moduł: co naprawdę wybieram, łącząc dwa obiekty Salesforce?

Narysowanie relacji jest łatwe. W rozdziale 2 rysowaliśmy linie i je nazywaliśmy: partner detaliczny wysyła wiele manifestów, dostawa zawiera wiele pozycji, ekipy i ciężarówki spotykają się w przydziale ekipy. Mówiliśmy o liczności, opcjonalności i historii. Teraz implementujemy te linie w Salesforce, a linia na diagramie zaczyna nieść dużo większy ciężar.

Wybierając typ relacji w Salesforce, nie mówię tylko, że te dwa rekordy są połączone. Mogę też decydować, kto jest właścicielem rekordu podrzędnego, czy może istnieć bez rodzica, kto może go widzieć, co się dzieje po usunięciu rodzica, czy może przejść do innego rodzica, czy mogę go podsumować na rodzicu i co się dzieje, gdy rekordów podrzędnych są setki tysięcy. Relacja to nie tylko linia. Niesie zachowanie.

Zanim przejdziesz do lookup czy master-detail, wróć do biznesu. Weźmy dostawę i jej pozycje: lodówkę, instalację, wywóz. Czy pozycja może istnieć bez swojej dostawy? Nie. Jeśli dostawa zostanie usunięta, czy jej pozycje też powinny zniknąć? Tak. Czy pozycje potrzebują własnego właściciela albo własnych zabezpieczeń? Właściwie nie. Czy ktoś powinien przenosić pozycję z jednej dostawy do drugiej? Miejmy nadzieję, że nie przypadkiem.

Teraz weźmy dostawę i trasę, na której jest. Dostawa istnieje, zanim trafi na trasę, może zostać przeniesiona na inną trasę, gdy zmienia się plan, a usunięcie trasy nigdy nie powinno usuwać dostaw na niej. Dwie linie jeden-do-wielu, które na diagramie wyglądają tak samo, a zachowują się zupełnie inaczej. Zwróć uwagę, że wciąż nie powiedzieliśmy „lookup” ani „master-detail”. Najpierw opisz zachowanie. Konfiguracja je implementuje.

Otwórz ekran Nowe pole, a Salesforce zaproponuje ci garść typów relacji (Object Relationships Overview (opens in a new tab), po angielsku):

  • Lookup (relacja wyszukiwania): łączy dwa obiekty. Chleb powszedni relacji w Salesforce.
  • Master-detail (nadrzędny-szczegółowy): wiązanie rodzic-dziecko, w którym rodzic kontroluje rekord podrzędny.
  • Wiele-do-wielu: nie osobny typ pola, ale wzorzec: obiekt łączący Salesforce (Salesforce Junction Object), czyli obiekt niestandardowy z dwiema relacjami master-detail.
  • Relacja do samego siebie (self-relationship): lookup z obiektu do niego samego.
  • Hierarchiczna: specjalny lookup, który istnieje tylko na obiekcie User, na przykład przełożony użytkownika.
  • Zewnętrzny lookup (external lookup) i pośredni lookup (indirect lookup): relacje do obiektów zewnętrznych i z nich, czyli obiektów __x z modułu 4. Zewnętrzny lookup wskazuje na nadrzędny obiekt zewnętrzny; pośredni lookup wskazuje z obiektu zewnętrznego na obiekt standardowy lub niestandardowy, dopasowując po unikalnym External ID.

Większość czasu projektowania idzie na pierwsze trzy. Weźmy je po kolei.

Lookup mówi: ten rekord jest powiązany z tamtym rekordem. Rekord podrzędny zachowuje własną tożsamość, własnego właściciela i własne życie. Dostawa wskazuje na swoją trasę. Jeśli trasa zostanie anulowana, dostawy nie znikają; wracają do ponownego planowania tras.

To zabawne: pole lookup trafia na rekord podrzędny, ale rodzic też coś dostaje: listę powiązaną (related list) swoich dzieci. Tworząc lookup, nazwij więc oba końce. Related List Label to to, co ludzie widzą na rodzicu, a Child Relationship Name to to, czego programiści i integracje używają, żeby przejść od rodzica do dzieci. Nie akceptuj wartości domyślnych.

Lookup może być wymagany albo opcjonalny. Gdy jest opcjonalny, decydujesz, co się stanie, jeśli rekord, na który wskazuje, zostanie usunięty, i są trzy możliwości (Considerations for Object Relationships (opens in a new tab), po angielsku):

  • Clear the value of this field (wyczyść wartość tego pola), domyślnie. Rekord podrzędny zostaje, z pustym lookupem.
  • Don’t allow deletion (nie pozwalaj na usunięcie) rekordu wskazywanego. Spróbuj usunąć trasę, a Salesforce odmówi: jest częścią relacji.
  • Delete this record also (usuń także ten rekord), czyli usuwanie kaskadowe, jak w master-detail. Ta opcja jest dostępna tylko dla niestandardowego lookupu na obiekcie niestandardowym, jest domyślnie wyłączona i Salesforce musi ją włączyć dla twojego orgu, bo usuwanie kaskadowe omija zabezpieczenia i udostępnianie: użytkownicy mogą usunąć rekordy, których nawet nie widzieli.

To decyzja o cyklu życia ukryta na ekranie konfiguracji.

Filtry lookupu (lookup filters) zawężają to, co użytkownik może wybrać. Powiedzmy, że dostawa ma lookup Installer do kontaktu, a instalatorzy to jeden typ rekordu kontaktu spośród wielu. Filtr lookupu pokazuje tylko instalatorów i może filtrować według bieżącego rekordu, według wyszukiwanego rekordu i według użytkownika: jego profilu, roli albo uprawnień (Lookup Filters (opens in a new tab), po angielsku). To tani sposób, żeby lookup był uczciwy.

Master-detail: ten rekord podrzędny należy do tamtego rodzica

Dział zatytułowany „Master-detail: ten rekord podrzędny należy do tamtego rodzica ”

Master-detail składa dużo mocniejszą deklarację. Na zajęciach nazywam to bardzo ścisłym wiązaniem. Nie możesz mieć rekordu szczegółowego bez nadrzędnego; pole nadrzędne jest wymagane. Rekord szczegółowy traci własne pole Właściciel i dziedziczy właściciela rodzica. Nie ma osobnej tabeli udostępniania dla rekordu szczegółowego, więc nie możesz udostępnić go osobno; dziedziczy udostępnianie rodzica. Dlatego obiekt szczegółowy nie może mieć reguł udostępniania, udostępniania ręcznego ani kolejek: wszystkie potrzebują pola Właściciel (Object Relationships Overview (opens in a new tab), po angielsku). W Konfiguracji jego ustawienie udostępniania brzmi Controlled by Parent (kontrolowane przez rodzica). A w samym polu master-detail wybierasz Sharing Setting (ustawienie udostępniania): czy użytkownik potrzebuje dostępu Read Only czy Read/Write do rekordu nadrzędnego, żeby tworzyć, edytować albo usuwać jego rekordy szczegółowe. Usunięcie rekordu nadrzędnego usuwa jego rekordy szczegółowe. A rekord nadrzędny dostaje pola podsumowania zbiorczego (roll-up summary).

Jeśli więc pozycja dostawy jest rekordem szczegółowym dostawy, mówię: ta pozycja należy do tej dostawy przez całe swoje życie. Na to pytanie chcę znać odpowiedź, zanim ktokolwiek wybierze w Konfiguracji relację master-detail.

Oto mój ulubiony sposób sprawdzenia, czy wszystko przemyśleliśmy: co powinno stać się z rekordami podrzędnymi, jeśli ktoś usunie rodzica? Wszyscy robią się niespokojni. Dobrze. Teraz uprawiamy architekturę.

Partner detaliczny ma setki tysięcy historycznych dostaw. Ktoś usuwa partnera. Czy dostawy powinny zniknąć? Niemal na pewno nie: zależą od nich reklamacje, rozliczenia i historia. Może usuwanie partnera w ogóle nie powinno być dozwolone, a partnera należy dezaktywować. W master-detail usunięcie rekordu nadrzędnego kaskadowo usuwa rekordy szczegółowe i ich rekordy szczegółowe; przywrócenie rekordu nadrzędnego je przywraca (Considerations for Object Relationships (opens in a new tab), po angielsku). Kiedy więc ktoś mówi „master-detail daje nam roll-upy”, odpowiadam: świetnie. Na co jeszcze właśnie się zgodziliśmy?

W lookup rekord podrzędny może mieć własnego właściciela. W master-detail nie może; dostęp wynika z rekordu nadrzędnego. To dokładnie właściwe, jeśli rekord szczegółowy naprawdę jest częścią rodzica. Ale jeśli rekord podrzędny potrzebuje własnego właściciela, własnego udostępniania albo własnego cyklu życia, model mówi ci, że master-detail to zły wybór. Następny moduł wchodzi głębiej we własność, a kurs Sharing and Visibility jeszcze dalej. Na razie: projekt relacji i projekt bezpieczeństwa to nie osobne rozmowy. Model danych kształtuje model bezpieczeństwa, zanim ktokolwiek napisze regułę udostępniania.

Czy rekord podrzędny może istnieć, zanim poznamy jego rodzica? To ważniejsze, niż się wydaje. Jeśli dostawy przychodzą w manifeście wieczorem poprzedniego dnia, a trasy buduje się potem, wymagana trasa na dostawie oznaczałaby, że planowanie tras musi nastąpić, zanim rekord w ogóle da się utworzyć. Relacja fizyczna musi obsługiwać prawdziwy cykl życia. Nie projektuję więc relacji wyłącznie na podstawie statycznego diagramu. Chcę wiedzieć: jak rekordy się rodzą, czy mogą istnieć same, czy mogą się przenosić i jak umierają?

Domyślnie rekordu podrzędnego w master-detail nie można przenieść do innego rodzica. Można na to pozwolić, zaznaczając w relacji Zezwalaj na zmianę rekordu nadrzędnego (Allow reparenting) (Considerations for Object Relationships (opens in a new tab), po angielsku). Mój instynkt jest zachowawczy: jeśli biznes mówi, że rekord podrzędny należy do jednego rodzica na całe życie, nie ułatwiam przenoszenia. Przejście pozycji z jednej dostawy do drugiej powinno być świadomym zdarzeniem biznesowym, a nie edycją pola. I znowu: ustawienie to nie architektura. Architekturą jest reguła cyklu życia, a ustawienie ją implementuje.

Dwie kolejne rzeczy, które później zaskakują zespoły. Nie da się utworzyć relacji master-detail na obiekcie, który już ma dane; tworzy się lookup, wypełnia go w każdym rekordzie, a potem konwertuje. A z powrotem na lookup da się przejść tylko wtedy, gdy na rekordzie nadrzędnym nie ma pól podsumowania zbiorczego. Zobacz też, co konwersja robi z bezpieczeństwem: zamiana lookupu w master-detail ustawia udostępnianie rekordu podrzędnego na Controlled by Parent, a zamiana master-detail z powrotem w lookup ustawia domyślne ustawienie dla całej organizacji (organization-wide default) rekordu podrzędnego na Public Read/Write (Considerations for Object Relationships (opens in a new tab), po angielsku). Rekordy, które wczoraj były prywatne, dziś są otwarte, dopóki ktoś tego nie zauważy. Wybierz wcześnie.

Lubię roll-upy. Policz pozycje dostawy, zsumuj kwoty pozycji faktury, znajdź najpóźniejszą datę: natywnie, bez kodu. Pole master-detail trafia na rekord podrzędny, ale roll-up trafia na rodzica. Mają jednak drobny druk (Roll-Up Summary Field (opens in a new tab), po angielsku):

  • Przeliczenie wartości roll-up po pewnych zmianach (nowe pole roll-up, zmieniona formuła, od której zależy, wymuszone przeliczenie) może trwać do 30 minut, zależnie od liczby objętych rekordów. Widziałem, jak ludzie zastanawiali się, dlaczego liczba na rodzicu jeszcze się nie zmieniła.
  • Nie da się podsumować wszystkiego. Autonumer nie może być polem, które agregujesz. A roll-up może podsumować pole formuły tylko wtedy, gdy ta formuła nie sięga do innego obiektu i nie używa funkcji, która zmienia się sama, takiej jak NOW() czy TODAY(). Formuła „dni po terminie” oparta na TODAY() zmienia się co noc, choć nikt nie zapisuje rekordu, więc roll-up nie ma od czego się przeliczyć. Taka liczba potrzebuje przepływu harmonogramowanego albo raportu.
  • Filtr też ma limity: żadnego długiego obszaru tekstowego, listy wielokrotnego wyboru, pola Description, pól systemowych takich jak Last Activity, formuł międzyobiektowych ani pól lookup.
  • Roll-upów nie ma na stronach edycji, więc reguła sprawdzania poprawności może z nich korzystać, ale nie może tam pokazać swojego błędu.

I nie odwracaj decyzji. Nie mów: „Potrzebujemy roll-upu, więc to musi być master-detail”. Mów: „Ten rekord podrzędny naprawdę należy do tego rodzica, własność i cykl życia pasują, a jedną z korzyści są natywne roll-upy”. Jeśli semantyka nie pasuje, rozwiąż obliczenie inaczej. Nie wykrzywiaj modelu danych, żeby dostać funkcję.

Jaki jest więc ten inny sposób? Budujesz roll-up sam: pole na rodzicu, które przechowuje wyliczoną wartość, i automatyzację, która utrzymuje je aktualne. Powiedzmy, że partner detaliczny jest lookupem z dostawy, tak jak powinien, a biznes chce mieć na partnerze liczbę otwartych dostaw (Open Deliveries). Dodaj do partnera pole liczbowe Open Deliveries. Potem przepływ wyzwalany rekordem (record-triggered flow) albo trigger Apex, gdy wolumen lub logika wymagają kodu, przelicza je przy każdej zmianie dostawy. Działa przez lookup, może filtrować po czymkolwiek i może używać dat i formuł, których natywny roll-up nie obsłuży.

Ale teraz to ty odpowiadasz za poprawność, i właśnie tu takie rozwiązania się sypią. Automatyzacja musi się uruchamiać przy każdej istotnej zmianie: nowym rekordzie podrzędnym, edytowanym, usuniętym, przywróconym i rekordzie podrzędnym przeniesionym do innego rodzica, co oznacza przeliczenie zarówno starego, jak i nowego rodzica. Musi obsłużyć ładowanie danych po 200 rekordów naraz bez przekraczania limitów. Przeliczaj od nowa, zamiast dodawać i odejmować, żeby jedno pominięte zdarzenie nie zostawiło błędnej liczby na zawsze. Zaplanuj sposób przeliczenia wszystkiego, na pierwsze ładowanie i na dzień, w którym wartości się rozjadą. I pamiętaj, że każdy zapis rekordu podrzędnego aktualizuje teraz rodzica, więc rodzic z tysiącami dzieci przywraca blokowanie, które zaraz zobaczymy. Natywny roll-up robi to wszystko za ciebie; własny to mały kawałek oprogramowania, którego jesteś właścicielem.

Trzy poziomy w głąb: piętrowanie relacji master-detail

Dział zatytułowany „Trzy poziomy w głąb: piętrowanie relacji master-detail ”

Platforma ma kształt, a master-detail ma dwa jego wymiary. Pierwszy to głębokość.

Relacje master-detail możesz piętrować na trzy niestandardowe poziomy szczegółowe w głąb i na tym koniec (Considerations for Object Relationships (opens in a new tab), po angielsku). Na zajęciach rysuję to jako konto z zamówieniem (jeden), zamówienie z pozycjami (dwa) i pozycje z ich szczegółami (trzy), a potem próbuję dodać czwarty i Salesforce mi nie pozwala. W Steve Trucking mogłoby to wyglądać tak: dostawa (Delivery) jest rekordem nadrzędnym; jej pozycje dostawy (Delivery Items) to pierwszy poziom; zadania instalacyjne pozycji (Install Tasks) to drugi; a kroki zadania (Task Steps) każdego zadania to trzeci. Czwarty poziom, powiedzmy notatka do kroku (Step Note), musi być lookupem.

Trzy poziomy master-detail Trzy spiętrowane relacje master-detail w Steve Trucking, narysowane grubymi liniami. Dostawa jest rekordem nadrzędnym. Pozycja dostawy to poziom szczegółowy 1, zadanie instalacyjne to poziom 2, a krok zadania to poziom 3. Notatka do kroku wisi na kroku zadania na cienkiej linii lookup, bo czwarty poziom musi być lookupem. Na dole: własność, udostępnianie i usuwanie spływają od dostawy na każdy poziom. poziom 1 poziom 2 poziom 3 czwarty poziom to lookup Dostawa Delivery__c · nadrzędny Pozycja dostawy Delivery_Item__c Zadanie instalacyjne Install_Task__c Krok zadania Task_Step__c Notatka do kroku Step_Note__c Własność, udostępnianie i usuwanie spływają od dostawy na każdy poziom. dokładnie jeden zero lub jeden jeden lub wiele zero lub wiele nadrzędny-szczegółowy wyszukiwanie © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Ze stosem przychodzi kilka zasad:

  • Obiekty standardowe nie mogą być po stronie szczegółowej obiektu niestandardowego. Obiekt niestandardowy może być rekordem szczegółowym konta; konto nie może być rekordem szczegółowym twojego obiektu.
  • Obiekt może wystąpić tylko raz w wielopoziomowym stosie. Salesforce nie chce, żebyś zawracał do samego siebie: rekord podszczegółowy nie może być jednocześnie rekordem nadrzędnym własnego rekordu nadrzędnego.
  • Rekord nadrzędny nie może bezpośrednio podsumować najniższego poziomu. Jeśli dostawa chce liczby kroków zadań, zadanie instalacyjne podsumowuje swoje kroki, pozycja dostawy podsumowuje te podsumowania, a dostawa podsumowuje pozycje: poziom po poziomie.
  • Własność i udostępnianie przychodzą z góry. Każdy poziom dziedziczy właściciela i dostęp rekordu nadrzędnego.
  • Usunięcie rekordu nadrzędnego usuwa wszystko pod nim, a jego przywrócenie przywraca wszystko.

Trzy poziomy zwykle w zupełności wystarczą. Jeśli twój projekt wciąż chce czwartego, zapytaj, czy każdy poziom naprawdę należy do tego nad nim przez całe życie. I pamiętaj, że to ty wybierasz, które ogniwo przerywa łańcuch. Czwarty poziom nie musi być lookupem: może zadanie instalacyjne tak naprawdę nie należy do swojej pozycji dostawy, bo jest planowane i przydzielane osobno, więc to ogniwo staje się lookupem, a zadanie instalacyjne zaczyna nowy łańcuch z krokiem zadania i notatką do kroku pod sobą. Wybierz ogniwo, w którym rekord podrzędny naprawdę ma własne życie, i to z niego zrób lookup.

Przerwanie łańcucha lookupem Te same pięć obiektów Steve Trucking co w stosie trzech poziomów, z lookupem pośrodku. Dostawa jest rekordem nadrzędnym, a pozycja dostawy jej rekordem szczegółowym na grubej linii master-detail. Pozycja dostawy łączy się z zadaniem instalacyjnym cienką linią lookup, która przerywa łańcuch. Zadanie instalacyjne jest nowym rekordem nadrzędnym: krok zadania jest jego rekordem szczegółowym, a notatka do kroku rekordem szczegółowym kroku zadania, obie na grubych liniach master-detail. Na dole: zadanie instalacyjne ma teraz własnego właściciela i udostępnianie, a usunięcie dostawy nie usuwa już jej zadań instalacyjnych. poziom 1 lookup przerywa łańcuch poziom 1 poziom 2 Dostawa Delivery__c · nadrzędny Pozycja dostawy Delivery_Item__c Zadanie instalacyjne Install_Task__c · nowy nadrzędny Krok zadania Task_Step__c Notatka do kroku Step_Note__c Zadanie instalacyjne ma teraz własnego właściciela i udostępnianie, a usunięcie dostawy nie usuwa już jej zadań instalacyjnych. dokładnie jeden zero lub jeden jeden lub wiele zero lub wiele nadrzędny-szczegółowy wyszukiwanie © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Teraz zadanie instalacyjne ma własnego właściciela i własne udostępnianie, dostawę można usunąć, nie zabierając ze sobą jej zadań instalacyjnych, a pod zadaniem instalacyjnym zmieszczą się jeszcze dwa poziomy. Taki jest kompromis: łańcuch jest krótszy, a życie zadania instalacyjnego należy do niego samego.

Dwóch rodziców wszerz: obiekt łączący Salesforce

Dział zatytułowany „Dwóch rodziców wszerz: obiekt łączący Salesforce ”

Najpierw słowo o słowach, bo „obiekt łączący” znaczy dwie rzeczy i uczę obu.

W rozdziale 2 znaleźliśmy logiczny obiekt łączący: połączenie dwóch kluczowych pojęć, które staje się osobną rzeczą, z własnymi atrybutami. Pies zna wiele sztuczek, sztuczkę zna wiele psów, a sztuczka psa siedzi między nimi i przechowuje poziom umiejętności i datę. To logiczny obiekt łączący, w modelu logicznym, na długo zanim ktokolwiek zdecyduje o lookup czy master-detail.

Salesforce używa tego terminu węziej. Gdy Salesforce mówi „junction object”, ma na myśli obiekt niestandardowy z dwiema relacjami master-detail (Create a Many-to-Many Object Relationship (opens in a new tab), po angielsku). Będę go nazywał obiektem łączącym Salesforce (Salesforce Junction Object). Każdy obiekt łączący Salesforce jest logicznym obiektem łączącym, ale nie każdy logiczny obiekt łączący staje się obiektem łączącym Salesforce: zbuduj go z jedną relacją master-detail i jednym lookupem albo z dwoma lookupami, a nadal będzie logicznym obiektem łączącym, tylko nie w wydaniu Salesforce. (Salesforce sam nie jest tu idealnie konsekwentny: jego własna dokumentacja obiektów nazywa niektóre obiekty standardowe zbudowane na lookupach „junction objects”. Na egzaminie przyjmij wąską definicję).

Wiedza egzaminacyjna. Obiekt łączący Salesforce (Salesforce Junction Object) to obiekt niestandardowy z dwiema relacjami master-detail i to właśnie Salesforce ma na myśli, mówiąc „junction object”. Logiczny obiekt łączący to szersza idea modelowania: dowolny obiekt, który łączy dwa inne w relacji wiele-do-wielu i niesie własne atrybuty, niezależnie od tego, jak go zbudowano.

Drugi wymiar to szerokość. Czy rekord podrzędny może mieć dwóch rodziców master-detail? Tak. Trzech? Nie. Każdy obiekt niestandardowy może mieć najwyżej dwie relacje master-detail (Considerations for Object Relationships (opens in a new tab), po angielsku). Dwóch rodziców master-detail to sposób na zbudowanie obiektu łączącego Salesforce dla relacji wiele-do-wielu. Ekipa (Crew) i ciężarówka (Truck) spotykają się w przydziale ekipy (Crew Assignment), a jak ustaliliśmy w rozdziale 2, to nie hydraulika: ma datę, trasę, może status. Obiekt łączący to miejsce, w którym relacja staje się pojęciem biznesowym. Wskazówki Salesforce do jego budowy: nadaj mu nazwę, która mówi, czym jest, niech nazwa rekordu będzie autonumerem i zmień nazwę listy powiązanej każdego rekordu nadrzędnego na nazwę drugiego rodzica, tak żeby strona ekipy pokazywała „Ciężarówki”, a strona ciężarówki „Ekipy” (Create a Many-to-Many Object Relationship (opens in a new tab), po angielsku).

A teraz zawiłość. Jeden z dwóch rodziców jest główny (primary) i jest nim ten, którego pole master-detail utworzono jako pierwsze. Nic wizualnie nie wskazuje, który to jest, więc to klasyczne pytanie egzaminacyjne i klasyczna niespodzianka.

O czym decyduje rodzic główny? O trzech rzeczach (Create a Many-to-Many Object Relationship (opens in a new tab), po angielsku):

  • Wygląd. Strony obiektu łączącego używają koloru i ikony głównego rekordu nadrzędnego.
  • Właściciel. Rekordy obiektu łączącego dziedziczą właściciela głównego rekordu nadrzędnego. Nigdy go nie widzisz, bo rekord szczegółowy nie ma pola Właściciel; ma to znaczenie tylko wtedy, gdy później usuniesz obie relacje master-detail.
  • Dział (Division), jeśli twój org używa działów, w ten sam sposób.

A drugi jest drugorzędny (secondary). Co to znaczy?

  • Jest następny w kolejce do roli głównego. Usuń główne pole master-detail albo przekonwertuj je na lookup, a drugorzędny stanie się główny.
  • Wyznacza zakres raportów. Salesforce daje ci dwa typy raportów: „Primary master with junction object and secondary master” oraz „Secondary master with junction object and primary master”. Rekord nadrzędny wymieniony jako pierwszy decyduje, które rekordy raport może pokazać.
  • Liczy się tak samo przy dostępie. Ujmuję to tak: własność od głównego, dostęp od obu, a wygrywa najbardziej restrykcyjny. Obiekt łączący, jak każdy obiekt szczegółowy, nie ma własnej tabeli udostępniania. Salesforce sprawdza dostęp użytkownika do obu rekordów nadrzędnych, przez Sharing Setting w każdym polu master-detail. Jeśli oba są ustawione na Read/Write, użytkownik potrzebuje Read/Write do ekipy i do ciężarówki, żeby edytować przydział ekipy (Considerations for Object Relationships (opens in a new tab), po angielsku).
  • Usuwa tak samo. Usuń którykolwiek rekord nadrzędny, ekipę albo ciężarówkę, a jego rekordy obiektu łączącego trafią do Kosza. Usuń oba, a znikną na dobre.
Główny i drugorzędny rodzic obiektu łączącego Obiekt łączący pod swoimi dwoma rodzicami master-detail, narysowany grubymi liniami. Ekipa, u góry po lewej, jest główna, bo jej pole master-detail utworzono jako pierwsze; daje przydziałowi ekipy właściciela i wygląd. Ciężarówka, u góry po prawej, jest drugorzędna; decyduje o zakresie drugiego typu raportu i staje się główna, jeśli pierwsza relacja zostanie usunięta. Przydział ekipy jest między nimi i pod nimi. Na dole: dostęp wymaga obu rodziców, a wygrywa najbardziej restrykcyjny; usuń któregokolwiek rodzica, a przydział też zniknie. właściciel i wygląd zakres raportów Ekipa Crew__c · główna: utworzona pierwsza Ciężarówka Truck__c · drugorzędna Przydział ekipy Crew_Assignment__c Dostęp wymaga obu rodziców: wygrywa najbardziej restrykcyjny. Usuń któregokolwiek rodzica, a przydział też zniknie. dokładnie jeden zero lub jeden jeden lub wiele zero lub wiele nadrzędny-szczegółowy © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Kilka kolejnych zasad: oba rekordy nadrzędne mogą mieć podsumowania zbiorcze z obiektu łączącego, a formuły i reguły sprawdzania poprawności obiektu łączącego mogą sięgać do pól obu. Ale obiekt łączący nie może być rekordem nadrzędnym niczego innego, więc nie może stać w środku stosu, a dwa rekordy nadrzędne nie mogą być tym samym obiektem; relacja wiele-do-wielu z obiektu do niego samego wymaga innego projektu. A jeśli rodzic ma ponad 200 rekordów obiektu łączącego, a obiekt łączący podsumowuje się do drugiego rodzica, Salesforce nie pozwoli usunąć tego rodzica, dopóki nie usuniesz wystarczająco wielu z nich.

Który rodzic powinien więc być główny? Utwórz najpierw ten, który jest właścicielem znaczenia. W przydziale ekipy pracę wykonuje ekipa, więc utworzyłbym najpierw ekipę. A potem to zapisz, bo nic na ekranie nie powie tego następnej osobie.

Po tym wszystkim przyznam, że nie kończę z wieloma obiektami łączącymi Salesforce. Zwykle obiekt ma jednego rodzica master-detail i są to dane tego samego rodzaju: dane klienta pod danymi klienta, transakcyjne pod transakcyjnymi (pamiętasz rodzaje danych z rozdziału 2: klienta, transakcyjne, referencyjne). Gdy jego drugi rodzic jest innego rodzaju, zwykle obiektem referencyjnym, ta relacja jest lookupem. Pozycja dostawy należy do swojej dostawy: master-detail, obie transakcyjne. Na produkt, który przewozi, wskazuje lookupem, bo produkt to dane referencyjne z własnym życiem i nikt nie chce, żeby usunięcie produktu zabrało ze sobą lata historii dostaw. Pozycja dostawy nadal jest logicznym obiektem łączącym między dostawą a produktami na niej; po prostu nie jest obiektem łączącym Salesforce.

Obiekt może wiązać się sam ze sobą: konto nadrzędne, przełożony, centrum dystrybucyjne podlegające regionalnemu węzłowi. Salesforce ma wbudowane dwie takie relacje, które spotkasz niemal w każdym orgu: konto do konta, czyli pole konto nadrzędne (Parent Account), które buduje hierarchię kont, oraz zgłoszenie do zgłoszenia, czyli zgłoszenie nadrzędne (Parent Case) z modułu 2, które grupuje powiązane zgłoszenia. Relacja do samego siebie musi być lookupem, a rekord nie może wskazywać na siebie, choć dwa rekordy mogą wskazywać na siebie nawzajem (Considerations for Object Relationships (opens in a new tab), po angielsku). Na obiekcie User to osobny, specjalny typ, relacja hierarchiczna, używana na przykład do przełożonego użytkownika. Mechanika jest prosta; liczy się nazewnictwo. Lookup z centrum dystrybucyjnego do centrum dystrybucyjnego o nazwie Distribution_Center__c nikomu nie pomaga. Nadrzędne? Zapasowe? Na nadmiar? Nazwij relację według roli, a nie według obiektu, na który wskazuje.

Relacje do samego siebie Trzy obiekty, każdy z lookupem do samego siebie. Konto przez pole ParentId wskazuje konto nadrzędne, co buduje hierarchię kont. Zgłoszenie przez pole ParentId wskazuje zgłoszenie nadrzędne. Centrum dystrybucyjne, obiekt niestandardowy, wskazuje swój regionalny węzeł przez pole o nazwie Regional_Hub__c. Na dole: zawsze lookup, nigdy do tego samego rekordu i nazwany według pełnionej roli. konto nadrzędne zgłoszenie nadrzędne regionalny węzeł Konto Account · ParentId Zgłoszenie Case · ParentId Centrum dystrybucyjne Distribution_Center__c · Regional_Hub__c Zawsze lookup, nigdy do tego samego rekordu i nazwany według pełnionej roli. dokładnie jeden zero lub jeden jeden lub wiele zero lub wiele wyszukiwanie © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Ta jest mała i to dokładnie ten rodzaj mało znanego, jedynego w swoim rodzaju faktu, po który spodziewałbym się, że sięgnie egzamin. Relacja hierarchiczna to specjalny lookup, który istnieje tylko na obiekcie User. Łączy jednego użytkownika z innym, a Salesforce nie pozwala, żeby łańcuch zawrócił: użytkownik nie może wskazywać na siebie, ani bezpośrednio, ani pośrednio (Object Relationships Overview (opens in a new tab), po angielsku). Jeśli przełożonym Marii jest Dev, przełożoną Deva nie może być Maria ani nikt, kto podlega Marii.

Na tym polega różnica wobec relacji do samego siebie opisanych wyżej. Na koncie albo obiekcie niestandardowym dwa rekordy mogą wskazywać na siebie nawzajem. Na obiekcie User hierarchia musi pozostać hierarchią. I to jedyny sposób powiązania użytkownika z użytkownikiem: zwykły lookup z User do User nie jest dostępny.

Jedną już masz. Standardowe pole Manager na obiekcie User to relacja hierarchiczna i mogą z niej korzystać zatwierdzenia: wyślij ten wniosek do przełożonego zgłaszającego. Możesz też tworzyć własne, na przykład Escalation Contact albo Backup Approver, a zatwierdzenie może być kierowane wzdłuż nich w ten sam sposób (ApprovalProcess, Metadata API (opens in a new tab), po angielsku). Nie myl jej z hierarchią ról, która steruje dostępem do rekordów. Pole hierarchiczne to tylko relacja między użytkownikami; nie udostępnia ani jednego rekordu.

Wiedza egzaminacyjna. Relacja hierarchiczna istnieje tylko na obiekcie User, jak standardowe pole Manager, a użytkownik nie może wskazywać na siebie, ani bezpośrednio, ani pośrednio. To nie jest hierarchia ról.

Każdy obiekt może mieć co najwyżej dwie relacje master-detail. Pola lookup i master-detail razem liczą się jako pola relacji: domyślnie 40 na obiekt, maksymalnie 50 na wniosek. Pola podsumowania zbiorczego: domyślnie 25 na obiekt, maksymalnie 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), po angielsku). Salesforce dodaje, że podniesienie któregokolwiek limitu może wpłynąć na wydajność.

Nie musisz projektować pod te liczby; musisz zauważyć, kiedy się do nich zbliżasz. Obiekt, na którym wisi relacja za relacją, coś ci mówi. Może naprawdę jest tak centralny. A może model jest zły. (I obowiązuje zasada zapasu z rozdziału 18: trzymaj się wyraźnie poniżej limitu, mierząc w trzecim roku).

Jest też rodzic ze zbyt wieloma dziećmi. Własne zalecenie Salesforce mówi, żeby nie przekraczać około 10 000 rekordów podrzędnych na jednego rodzica w relacji master-detail (Considerations for Object Relationships (opens in a new tab), po angielsku), a przewodnik po dostępie do rekordów w dużej skali mówi to samo o relacjach rodzic-dziecko ogólnie (Parent-Child Data Skew (opens in a new tab), po angielsku). Rekord 10 001 nie psuje orgu. Ale powyżej tego progu zapis rekordu podrzędnego może blokować rodzica, a zmiany udostępniania na rodzicu rozchodzą się na każdy rekord podrzędny.

Kiedy więc widzę jednego rodzica i ogromną liczbę dzieci, pytam: dlaczego wszystkie są pod tym samym rodzicem, kto jest ich właścicielem, jak się je odpytuje i jaka automatyzacja dotyka rodzica? Wszystkie dostawy pod jednym kontem „Steve Trucking” przekroczyłyby 10 000 w kilka dni. Niewinna relacja jeden-do-wielu staje się problemem nierównomiernego rozkładu. Następny moduł zapowiada ten temat, a część 2 wchodzi w niego głęboko.

Oto nawyk, którego chcę z tego modułu. Nie zaczynaj od „potrzebuję roll-upu”, „potrzebuję, żeby było wymagane”, „chcę dziedziczonego udostępniania”. To wskazówki implementacyjne. Zacznij od biznesu: czy rekord podrzędny ma własne życie, kto jest jego właścicielem, czy może istnieć sam, czy może się przenosić, co się dzieje, gdy rodzic znika, czy relacja niesie dane i jak duża może być każda strona? Potem wybierz relację, która implementuje odpowiedzi.

Lookup, master-detail czy obiekt łączący? Macierz trzech wzorców relacji zestawionych z sześcioma pytaniami biznesowymi. Lookup: rekord podrzędny może istnieć samodzielnie, ma własnego właściciela, może zmienić rodzica i radzi sobie z ponad 10 000 rekordów podrzędnych na rodzica, choć nadal trzeba pilnować nierównomiernego rozkładu danych; domyślnie nie odchodzi z rodzicem (pole jest czyszczone albo usunięcie jest blokowane) i trzyma jednego rodzica na pole. Znaczy „połączone”. Master-detail: rodzic jest wymagany, rekord podrzędny dziedziczy właściciela rodzica, jest usuwany kaskadowo razem z rodzicem, zmienia rodzica tylko wtedy, gdy zezwolono na zmianę rekordu nadrzędnego, a ponad 10 000 rekordów podrzędnych oznacza blokady rodzica i przeliczenia. Znaczy „należy do”. Obiekt łączący Salesforce: potrzebuje obu rodziców, właściciela bierze od głównego, jest usuwany razem z którymkolwiek rodzicem i jest jedynym wzorcem dla relacji wiele po obu stronach. Znaczy „pojęcie biznesowe”. Na dole: najpierw odpowiedz na pytania biznesowe; typ relacji wynika z odpowiedzi. ISTNIEJE SAMODZIELNIE WŁASNY WŁAŚCICIEL ODCHODZI Z RODZICEM ZMIENIA RODZICA WIELE PO OBU STRONACH 10 000+ NA RODZICA ZNACZY Lookup Dostawa → Trasa domyślnie czyści albo blokuje jeden rodzic na pole nadal pilnuj skew POŁĄCZONE Master-detail Dostawa → Pozycja dostawy rodzic wymagany dziedziczy po rodzicu usuwanie kaskadowe tylko z włączoną zmianą rodzica jeden nadrzędny na pole blokady rodzica, przeliczenia NALEŻY DO Obiekt łączący Salesforce Ekipa + Ciężarówka → Przydział ekipy potrzebuje obu rodziców od głównego usuwa go każdy z rodziców tylko z włączoną zmianą rodzica to jego zadanie ta sama zasada 10 000 POJĘCIE BIZNESOWE Najpierw odpowiedz na pytania biznesowe. Typ relacji wynika z odpowiedzi; nie zaczynaj od funkcji, której chcesz. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Poza egzaminem: co zmienia AI. AI potrafi zaproponować relacje w kilka sekund. Nie powie ci, czy biznes kiedykolwiek usunie rodzica. Szybsze rysowanie diagramów nie sprawia, że błędną relację taniej odwrócić, gdy zależą od niej miliony rekordów i dziesiątki automatyzacji.

  • Czy rekord podrzędny ma własny cykl życia, czy naprawdę należy do rodzica, i czy własność i dostęp mają być własne, czy dziedziczone.
  • Czy rekord podrzędny może istnieć bez rodzica, przenosić się między rodzicami albo przetrwać usunięcie rodzica.
  • Co robi każdy lookup, gdy jego rodzic zostaje usunięty: czyści, blokuje czy usuwa kaskadowo.
  • Czy relacja wiele-do-wielu to hydraulika, czy pojęcie biznesowe, czy logiczny obiekt łączący staje się obiektem łączącym Salesforce, który rodzic jest główny i co obaj rodzice oznaczają dla dostępu.
  • Czy model pasuje do kształtu platformy: trzy niestandardowe poziomy szczegółowe w głąb, dwóch rodziców master-detail wszerz, limity relacji i roll-upów.
  • Czy oczekiwana liczba i rozkład rekordów podrzędnych tworzą ryzyko nierównomiernego rozkładu, które powinno zmienić projekt.

Relacja to zestaw obietnic o tym, jak dwa elementy danych zachowują się razem. Składaj je świadomie.