Siirry sisältöön

Suhteilla on seurauksia

Saatavilla myös 28 kielellä

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 · 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.
Kuva on luotu tekoälyllä

Moduuli 7/10 luvussa Salesforcen tietoarkkitehtuuri, Data Architect -kurssin luku 3. Jokainen moduuli on itsenäinen. Edellinen: Kentätkin ovat arkkitehtuuria · Seuraava: Omistajuus ja elinkaari

Kysymys, johon tämä moduuli vastaa: Mitä oikeastaan valitsen, kun yhdistän kaksi Salesforce-objektia?

Suhteen piirtäminen on helppoa. Luvussa 2 piirsimme viivoja ja nimesimme ne: vähittäiskauppakumppani lähettää monta kuormaluetteloa, toimitus kuljettaa monta riviä, tiimit ja kuorma-autot kohtaavat tiimin osoituksessa (Crew Assignment). Puhuimme kardinaliteetista, valinnaisuudesta ja historiasta. Nyt toteutamme nuo viivat Salesforcessa, ja kaavion viiva alkaa kantaa paljon enemmän painoa.

Kun valitsen suhdetyypin Salesforcessa, en vain sano, että nämä kaksi tietuetta ovat yhteydessä. Saatan samalla päättää, kuka omistaa lapsen, voiko se olla olemassa ilman vanhempaa, kuka voi nähdä sen, mitä tapahtuu, kun vanhempi poistetaan, voiko se siirtyä toiselle vanhemmalle, voinko koota siitä yhteenvedon vanhempaan ja mitä tapahtuu, kun lapsia on satoja tuhansia. Suhde ei ole vain viiva. Se kantaa toimintaa.

Ennen lookupia tai master-detailia palaa liiketoimintaan. Otetaan toimitus ja sen toimitusrivit (Delivery Item): jääkaappi, asennus, vanhan laitteen poisvienti. Voiko rivi olla olemassa ilman toimitustaan? Ei. Jos toimitus poistetaan, pitäisikö sen rivienkin lähteä? Kyllä. Tarvitsevatko rivit oman omistajan tai oman suojauksen? Eivät oikeastaan. Pitäisikö kenenkään siirtää riviä toimituksesta toiseen? Toivottavasti ei vahingossa.

Otetaan sitten toimitus ja reitti (Route), jolla se on. Toimitus on olemassa ennen kuin se reititetään, sen voi siirtää toiselle reitille, kun suunnitelma muuttuu, eikä reitin poistamisen pitäisi koskaan poistaa sen toimituksia. Kaksi yksi-moneen-viivaa, jotka näyttävät kaaviossa samalta mutta toimivat täysin eri tavoin. Huomaa, ettemme ole vieläkään sanoneet ”lookup” tai ”master-detail”. Kuvaa ensin toiminta. Määritys toteuttaa sen.

Avaa New Field -näkymä, niin Salesforce tarjoaa kourallisen suhdetyyppejä (Object Relationships Overview (opens in a new tab)):

  • Lookup: yhdistää kaksi objektia. Salesforcen suhteiden perusruokaa.
  • Master-detail: vanhemman ja lapsen sidos, jossa vanhempi hallitsee lasta.
  • Monta-moneen: ei oma kenttätyyppinsä vaan malli: Salesforcen liitosobjekti (Salesforce Junction Object), mukautettu objekti, jossa on kaksi master-detail-suhdetta.
  • Itseensä viittaava suhde (self-relationship): lookup objektista itseensä.
  • Hierarkkinen (hierarchical): erityinen lookup, jota on vain User-objektissa, kuten käyttäjän esihenkilö.
  • External lookup ja indirect lookup: suhteet ulkoisiin objekteihin ja niistä, moduulin 4 __x-objekteihin. External lookup osoittaa ulkoiseen vanhempiobjektiin; indirect lookup osoittaa ulkoisesta objektista vakio- tai mukautettuun objektiin, ja täsmäys tehdään yksilöllisen External ID:n perusteella.

Suurin osa suunnitteluajastasi menee kolmeen ensimmäiseen. Käydään ne läpi yksi kerrallaan.

Lookup: nämä tietueet ovat yhteydessä

Osio nimeltä “Lookup: nämä tietueet ovat yhteydessä ”

Lookup sanoo: tämä tietue liittyy tuohon tietueeseen. Lapsi säilyttää oman olemassaolonsa, oman omistajansa ja oman elämänsä. Toimitus osoittaa reittiinsä. Jos reitti perutaan, toimitukset eivät katoa; ne palaavat reititettäviksi uudelleen.

Hauska juttu: lookup-kenttä tulee lapseen, mutta vanhempikin saa jotain, lastensa liittyvän luettelon (related list). Joten kun luot sellaisen, nimeä molemmat päät. Related List Label on se, mitä ihmiset näkevät vanhemmassa, ja Child Relationship Name on se, mitä kehittäjät ja integraatiot käyttävät kulkiessaan vanhemmasta lapsiin. Älä hyväksy oletuksia.

Lookup voi olla pakollinen tai valinnainen. Kun se on valinnainen, päätät, mitä tapahtuu, jos tietue, johon se osoittaa, poistetaan, ja vaihtoehtoja on kolme (Considerations for Object Relationships (opens in a new tab)):

  • Clear the value of this field (tyhjennä tämän kentän arvo), oletus. Lapsi jää, ja lookup on tyhjä.
  • Don’t allow deletion (älä salli poistamista) lookup-tietueelle. Yritä poistaa reitti, niin Salesforce sanoo ei: se on osa suhdetta.
  • Delete this record also (poista myös tämä tietue), ketjupoisto kuten master-detailissa. Sitä tarjotaan vain mukautetun objektin mukautetulle lookupille, se on oletuksena pois käytöstä, ja Salesforcen on otettava se käyttöön orgillesi, koska ketjupoisto ohittaa suojauksen ja jakamisen: käyttäjät voivat poistaa tietueita, joita he eivät edes nähneet.

Se on elinkaaripäätös, joka piileskelee Setup-näkymässä.

Lookup-suodattimet (lookup filters) rajaavat, mitä käyttäjä voi valita. Sanotaan, että toimituksella on Installer-lookup yhteyshenkilöön, ja asentajat ovat yksi yhteyshenkilöiden tietuetyyppi monien joukossa. Lookup-suodatin näyttää vain asentajat, ja se voi suodattaa nykyisen tietueen, haettavan tietueen ja käyttäjän perusteella: hänen profiilinsa, roolinsa tai käyttöoikeuksiensa (Lookup Filters (opens in a new tab)). Se on halpa tapa pitää lookup rehellisenä.

Master-detail: tämä lapsi kuuluu tuolle vanhemmalle

Osio nimeltä “Master-detail: tämä lapsi kuuluu tuolle vanhemmalle ”

Master-detail esittää paljon vahvemman väitteen. Kurssilla kutsun sitä hyvin tiukaksi sidokseksi. Detail-tietuetta ei voi olla ilman masteriaan; master-kenttä on pakollinen. Detail menettää oman Owner-kenttänsä ja perii vanhempansa omistajan. Detaililla ei ole erillistä jakotaulua (share table), joten lasta ei voi jakaa erikseen; se perii vanhempansa jakamisen. Siksi detail-objektilla ei voi olla jakamissääntöjä, manuaalista jakamista eikä jonoja: ne kaikki tarvitsevat Owner-kentän (Object Relationships Overview (opens in a new tab)). Setupissa sen jakamisasetuksena lukee Controlled by Parent (vanhemman hallitsema). Ja itse master-detail-kentässä valitset Sharing Setting -asetuksen: tarvitseeko käyttäjä masteriin Read Only- vai Read/Write-pääsyn luodakseen, muokatakseen tai poistaakseen sen detail-tietueita. Masterin poistaminen poistaa sen detail-tietueet. Ja master saa koontikentät (roll-up summary).

Jos siis toimitusrivi on toimituksen detail, sanon: tämä rivi kuuluu tälle toimitukselle koko elämänsä ajan. Siihen kysymykseen haluan vastauksen ennen kuin kukaan valitsee Setupissa Master-Detail Relationshipin.

Tässä lempitapani selvittää, olemmeko miettineet asian loppuun: mitä lapsille pitäisi tapahtua, jos joku poistaa vanhemman? Kaikkia alkaa vaivaannuttaa. Hyvä. Nyt teemme arkkitehtuuria.

Vähittäiskauppakumppanilla on satoja tuhansia historiallisia toimituksia. Joku poistaa kumppanin. Pitäisikö toimitusten kadota? Lähes varmasti ei: reklamaatiot, laskutus ja historia riippuvat niistä. Ehkä kumppanin poistamista ei pitäisi sallia lainkaan, vaan kumppani pitäisi sen sijaan passivoida. Master-detailissa masterin poistaminen ketjuuntuu sen detail-tietueisiin ja niiden detail-tietueisiin; masterin palauttaminen tuo ne takaisin (Considerations for Object Relationships (opens in a new tab)). Joten kun joku sanoo ”master-detail antaa meille koontikentät”, vastaukseni on: hienoa. Mihin muuhun juuri suostuit?

Lookupissa lapsella voi olla oma omistajansa. Master-detailissa ei voi; pääsy seuraa masteria. Se on juuri oikein, jos detail todella on osa vanhempaa. Mutta jos lapsi tarvitsee oman omistajan, oman jakamisen tai oman elinkaaren, malli kertoo sinulle, että master-detail on väärä valinta. Seuraava moduuli menee syvemmälle omistajuuteen, ja Sharing and Visibility -kurssi vielä pidemmälle. Tässä vaiheessa: suhteiden suunnittelu ja suojauksen suunnittelu eivät ole erillisiä keskusteluja. Tietomalli muovaa suojausmallia ennen kuin kukaan kirjoittaa jakamissääntöä.

Voiko lapsi olla olemassa ennen kuin tiedämme sen vanhemman? Sillä on enemmän merkitystä kuin miltä kuulostaa. Jos toimitukset saapuvat kuormaluettelossa edellisenä iltana ja reitit rakennetaan sen jälkeen, pakollinen reitti toimituksessa tarkoittaisi, että reititys on tehtävä ennen kuin tietuetta voi edes luoda. Fyysisen suhteen on tuettava todellista elinkaarta. En siis suunnittele suhteita pelkästä staattisesta kaaviosta. Haluan tietää: miten ne syntyvät, voivatko ne olla olemassa yksin, voivatko ne siirtyä ja miten ne kuolevat?

Oletuksena master-detail-lasta ei voi siirtää toiselle vanhemmalle. Sen voi sallia valitsemalla suhteessa Allow reparenting (Considerations for Object Relationships (opens in a new tab)). Vaistoni on varovainen: jos liiketoiminta sanoo, että lapsi kuuluu yhdelle vanhemmalle koko elämänsä, en tee sen siirtämisestä helppoa. Rivin siirtymisen toimituksesta toiseen pitäisi olla harkittu liiketoimintatapahtuma, ei kentän muokkaus. Jälleen kerran asetus ei ole arkkitehtuuri. Elinkaarisääntö on, ja asetus toteuttaa sen.

Kaksi asiaa lisää, jotka yllättävät tiimit myöhemmin. Master-detail-suhdetta ei voi luoda objektiin, jossa on jo tietoja; luot lookupin, täytät sen jokaiseen tietueeseen ja muunnat sen sitten. Ja takaisin lookupiksi voi muuntaa vain, jos masterissa ei ole koontikenttiä. Katso myös, mitä muuntaminen tekee suojaukselle: lookupin muuttaminen master-detailiksi asettaa lapsen jakamiseksi Controlled by Parent, ja master-detailin muuttaminen takaisin lookupiksi asettaa lapsen organisaationlaajuiseksi oletukseksi Public Read/Write (Considerations for Object Relationships (opens in a new tab)). Eilen yksityiset tietueet ovat tänään avoimia, kunnes joku huomaa. Valitse ajoissa.

Koontikentät ovat hyödyllisiä, mutta eivät ilmaisia

Osio nimeltä “Koontikentät ovat hyödyllisiä, mutta eivät ilmaisia ”

Pidän koontikentistä. Laske toimituksen rivit, summaa laskun rivisummat, löydä viimeisin päivämäärä: natiivisti, ilman koodia. Master-detail-kenttä tulee lapseen, mutta koontikenttä tulee vanhempaan. Niissä on kuitenkin pientä präntättyä (Roll-Up Summary Field (opens in a new tab)):

  • Koontiarvojen laskeminen tiettyjen muutosten jälkeen (uusi koontikenttä, muutettu kaava, josta se riippuu, pakotettu uudelleenlaskenta) voi kestää jopa 30 minuuttia sen mukaan, kuinka moneen tietueeseen muutos vaikuttaa. Olen nähnyt ihmisten ihmettelevän, miksi vanhemman luku ei ole vielä muuttunut.
  • Ne eivät voi koota kaikkea. Automaattinen numero ei voi olla kenttä, jota kootaan. Ja koontikenttä voi koota kaavakentän vain, jos kaava ei kurota toiseen objektiin eikä käytä funktiota, joka muuttuu itsestään, kuten NOW() tai TODAY(). TODAY()-funktion varaan rakennettu ”myöhässä päiviä” -kaava muuttuu joka yö ilman, että kukaan tallentaa tietuetta, joten koontikentällä ei ole mitään, mistä laskea uudelleen. Sellainen luku tarvitsee ajastetun flow’n tai raportin.
  • Suodattimellakin on rajansa: ei pitkiä tekstialueita, monivalintaluetteloita, Description-kenttiä, järjestelmäkenttiä kuten Last Activity, objektien välisiä kaavoja eikä lookup-kenttiä.
  • Koontikentät eivät ole muokkaussivuilla, joten vahvistussääntö voi käyttää sellaista mutta ei voi näyttää virhettään siellä.

Äläkä käännä päätöstä toisin päin. Älä sano: ”Tarvitsemme koontikentän, joten tämän on oltava master-detail.” Sano: ”Tämä lapsi todella kuuluu tälle vanhemmalle, omistajuus ja elinkaari sopivat, ja yksi hyödyistä on natiivit koontikentät.” Jos semantiikka ei sovi, ratkaise laskenta toisella tavalla. Älä vääristä tietomallia saadaksesi ominaisuuden.

Mikä se toinen tapa sitten on? Rakennat koonnin itse: vanhempaan kenttä, joka sisältää lasketun arvon, ja automaatio, joka pitää sen ajan tasalla. Sanotaan, että vähittäiskauppakumppani on lookup toimituksesta, kuten sen kuuluukin, ja liiketoiminta haluaa kumppaniin avoimien toimitusten määrän. Lisää kumppaniin lukukenttä, Open Deliveries. Sitten tietueen käynnistämä flow (record-triggered flow), tai Apex-trigger, kun volyymi tai logiikka vaatii koodia, laskee sen uudelleen aina, kun toimitus muuttuu. Se toimii lookupin yli, se voi suodattaa minkä tahansa perusteella, ja se voi käyttää päivämääriä ja kaavoja, joihin natiivi koontikenttä ei pysty.

Mutta nyt sen oikein saaminen on sinun vastuullasi, ja juuri tässä nämä menevät pieleen. Automaation on käynnistyttävä jokaisesta merkityksellisestä muutoksesta: uusi lapsi, muokattu lapsi, poistettu lapsi, palautettu lapsi ja lapsi, joka siirretään toiselle vanhemmalle, mikä tarkoittaa sekä vanhan että uuden vanhemman uudelleenlaskentaa. Sen on kestettävä 200 tietueen kerrallaan etenevä tietojen lataus rajoihin törmäämättä. Laske uudelleen alusta sen sijaan, että lisäisit ja vähentäisit, jotta yksi väliin jäänyt tapahtuma ei jätä lukua pysyvästi vääräksi. Suunnittele tapa laskea kaikki uudelleen, ensimmäistä latausta ja sitä päivää varten, kun luku ajautuu sivuun. Ja muista, että jokainen lapsen tallennus päivittää nyt vanhemman, joten vanhempi, jolla on tuhansia lapsia, tuo takaisin lukitukset, jotka näemme hetken päästä. Natiivi koontikenttä tekee kaiken tuon puolestasi; mukautettu on pieni ohjelmisto, jonka omistat.

Kolme tasoa syvä: master-detailien pinoaminen

Osio nimeltä “Kolme tasoa syvä: master-detailien pinoaminen ”

Alustalla on muoto, ja master-detailissa sillä on kaksi ulottuvuutta. Ensimmäinen on syvyys.

Master-detaileja voi pinota kolme mukautettua detail-tasoa syvälle, ja siihen pohja tulee vastaan (Considerations for Object Relationships (opens in a new tab)). Kurssilla piirrän sen tilinä, jolla on tilaus (yksi), tilauksena riveineen (kaksi) ja riveinä yksityiskohtineen (kolme), ja sitten yritän lisätä neljännen, eikä Salesforce anna. Steve Truckingissa se voisi näyttää tältä: toimitus (Delivery) on master; sen toimitusrivit (Delivery Item) ovat ensimmäinen taso; rivin asennustehtävät (Install Task) toinen; ja kunkin tehtävän tehtävävaiheet (Task Step) kolmas. Neljännen tason, vaikkapa vaiheen muistiinpanon (Step Note), on oltava lookup.

Kolme master-detail-tasoa Kolme päällekkäistä master-detail-suhdetta Steve Truckingissa paksuina viivoina. Toimitus on master. Toimitusrivi on detail tasolla 1, Asennustehtävä tasolla 2 ja Tehtävän vaihe tasolla 3. Vaiheen muistiinpano roikkuu Tehtävän vaiheesta ohuella lookup-viivalla, koska neljännen tason on oltava lookup. Alla: omistajuus, jakaminen ja poistaminen virtaavat toimituksesta alas jokaiselle tasolle. taso 1 taso 2 taso 3 neljäs taso on lookup Toimitus Delivery__c · master Toimitusrivi Delivery_Item__c Asennustehtävä Install_Task__c Tehtävän vaihe Task_Step__c Vaiheen muistiinpano Step_Note__c Omistajuus, jakaminen ja poistaminen virtaavat toimituksesta alas jokaiselle tasolle. täsmälleen yksi nolla tai yksi yksi tai monta nolla tai monta master-detail lookup © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Pinon mukana tulee muutama sääntö:

  • Vakio-objektit eivät voi olla mukautetun objektin detail-puolella. Mukautettu objekti voi olla tilin detail; tili ei voi olla sinun objektisi detail.
  • Objekti voi esiintyä vain kerran monitasoisessa pinossa. Salesforce ei halua, että kierrät takaisin itseesi: alidetail ei voi olla myös oman masterinsa master.
  • Master ei voi koota alinta tasoa suoraan. Jos toimitus haluaa tehtävävaiheiden määrän, asennustehtävä kokoaa vaiheensa, toimitusrivi kokoaa nuo koonnit ja toimitus kokoaa rivit: taso kerrallaan.
  • Omistajuus ja jakaminen tulevat ylhäältä. Jokainen taso perii masterin omistajan ja pääsyn.
  • Masterin poistaminen poistaa kaiken sen alla, ja sen palauttaminen tuo kaiken takaisin.

Kolme tasoa riittää yleensä hyvin. Jos suunnitelmasi haluaa jatkuvasti neljännen, kysy, kuuluuko jokainen taso todella yläpuolellaan olevalle koko elämänsä ajan. Ja muista, että saat valita, mikä linkki katkaisee ketjun. Neljännen tason ei tarvitse olla lookup: ehkä asennustehtävä ei todella kuulu toimitusriville, vaan se ajoitetaan ja osoitetaan omana itsenään, joten siitä linkistä tulee lookup, ja nyt asennustehtävä aloittaa uuden ketjun, jonka alla ovat tehtävävaihe ja vaiheen muistiinpano. Valitse linkki, jossa lapsella todella on oma elämänsä, ja tee siitä lookup.

Ketjun katkaiseminen lookupilla Samat viisi Steve Truckingin objektia kuin kolmen tason pinossa, keskellä lookup. Toimitus on master, ja Toimitusrivi on sen detail paksulla master-detail-viivalla. Toimitusrivi linkittyy Asennustehtävään ohuella lookup-viivalla, joka katkaisee ketjun. Asennustehtävä on uusi master: Tehtävän vaihe on sen detail, ja Vaiheen muistiinpano on Tehtävän vaiheen detail, molemmat paksuilla master-detail-viivoilla. Alla: asennustehtävällä on nyt oma omistaja ja jakaminen, eikä toimituksen poistaminen enää poista sen asennustehtäviä. taso 1 lookup katkaisee ketjun taso 1 taso 2 Toimitus Delivery__c · master Toimitusrivi Delivery_Item__c Asennustehtävä Install_Task__c · uusi master Tehtävän vaihe Task_Step__c Vaiheen muistiinpano Step_Note__c Asennustehtävällä on nyt oma omistaja ja jakaminen, eikä toimituksen poistaminen enää poista sen asennustehtäviä. täsmälleen yksi nolla tai yksi yksi tai monta nolla tai monta master-detail lookup © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Nyt asennustehtävällä on oma omistajansa ja oma jakamisensa, toimituksen voi poistaa viemättä sen asennustehtäviä mukanaan, ja asennustehtävän alla voi olla kaksi tasoa lisää. Se on vaihtokauppa: ketju on lyhyempi, ja asennustehtävän elämä on sen oma.

Kaksi vanhempaa leveä: Salesforcen liitosobjekti

Osio nimeltä “Kaksi vanhempaa leveä: Salesforcen liitosobjekti ”

Ensin sana sanoista, koska ”liitosobjekti” (junction object) tarkoittaa kahta asiaa, ja opetan molemmat.

Luvussa 2 löysimme loogisen liitosobjektin: kahden keskeisen käsitteen liitoksen, josta tulee oma asiansa omine attribuutteineen. Koira osaa monta temppua, monta koiraa osaa saman tempun, ja koiran temppu on niiden välissä kantaen taitotason ja päivämäärän. Se on looginen liitosobjekti, loogisessa mallissa, kauan ennen kuin kukaan päättää lookupista tai master-detailista.

Salesforce käyttää termiä suppeammin. Kun Salesforce sanoo junction object, se tarkoittaa mukautettua objektia, jossa on kaksi master-detail-suhdetta (Create a Many-to-Many Object Relationship (opens in a new tab)). Kutsun sitä Salesforcen liitosobjektiksi (Salesforce Junction Object). Jokainen Salesforcen liitosobjekti on looginen liitosobjekti, mutta jokaisesta loogisesta liitosobjektista ei tule Salesforcen liitosobjektia: rakenna se yhdellä master-detaililla ja yhdellä lookupilla tai kahdella lookupilla, niin se on yhä looginen liitosobjekti, vain ei Salesforcen lajia. (Salesforce ei ole itsekään täysin johdonmukainen: sen oma objektiviite kutsuu joitakin lookupien varaan rakennettuja vakio-objekteja ”junction objecteiksi”. Kokeessa oleta suppea määritelmä.)

Koetieto. Salesforcen liitosobjekti (Salesforce Junction Object) on mukautettu objekti, jossa on kaksi master-detail-suhdetta, ja sitä Salesforce tarkoittaa, kun se sanoo ”junction object”. Looginen liitosobjekti on laajempi mallinnusajatus: mikä tahansa objekti, joka yhdistää kaksi muuta monta-moneen-suhteessa ja kantaa omia attribuuttejaan, rakennettiinpa se miten tahansa.

Toinen ulottuvuus on leveys. Voiko lapsella olla kaksi master-detail-vanhempaa? Kyllä. Kolme? Ei. Jokaisella mukautetulla objektilla voi olla enintään kaksi master-detail-suhdetta (Considerations for Object Relationships (opens in a new tab)). Kahdella master-detail-vanhemmalla rakennetaan Salesforcen liitosobjekti monta-moneen-suhteelle. Tiimi (Crew) ja kuorma-auto (Truck) kohtaavat tiimin osoituksessa (Crew Assignment), ja kuten luvussa 2 huomasimme, se ei ole putkistoa: sillä on päivämäärä, reitti, ehkä tila. Liitos on kohta, jossa suhteesta tulee liiketoimintakäsite. Salesforcen vinkit sellaisen rakentamiseen: anna sille nimi, joka kertoo, mikä se on, tee sen tietueen nimestä automaattinen numero ja nimeä kummankin masterin liittyvä luettelo toisen masterin mukaan, jotta tiimin sivulla näkyy ”Trucks” ja kuorma-auton sivulla ”Crews” (Create a Many-to-Many Object Relationship (opens in a new tab)).

Tässä on hienous. Toinen kahdesta vanhemmasta on ensisijainen (primary), ja se on se, jonka master-detail-kentän loit ensin. Mikään ei näytä visuaalisesti, kumpi se on, joten se on klassinen koekysymys ja klassinen yllätys.

Mitä ensisijainen ratkaisee? Kolme asiaa (Create a Many-to-Many Object Relationship (opens in a new tab)):

  • Ulkoasu. Liitoksen sivut käyttävät ensisijaisen masterin väriä ja kuvaketta.
  • Omistaja. Liitostietueet perivät ensisijaisen master-tietueen omistajan. Et koskaan näe sitä, koska detaililla ei ole Owner-kenttää; sillä on merkitystä vain, jos myöhemmin poistat molemmat master-detail-suhteet.
  • Divisioona (Division), jos orgisi käyttää divisioonia, samalla tavalla.

Ja toinen on toissijainen (secondary). Mitä se tarkoittaa?

  • Se on jonossa ensisijaiseksi. Poista ensisijainen master-detail-kenttä tai muunna se lookupiksi, niin toissijaisesta tulee ensisijainen.
  • Se asettaa raporttien laajuuden. Salesforce antaa kaksi raporttityyppiä: ”Primary master with junction object and secondary master” ja ”Secondary master with junction object and primary master”. Ensimmäisenä mainittu master ratkaisee, mitä tietueita raportti voi näyttää.
  • Se merkitsee pääsyssä yhtä paljon. Näin sanon sen: omistajuus ensisijaiselta, pääsy molemmilta, ja tiukin voittaa. Liitoksella, kuten millä tahansa detaililla, ei ole omaa jakotaulua. Salesforce tarkistaa käyttäjän pääsyn molempiin master-tietueisiin kummankin master-detail-kentän Sharing Setting -asetuksen kautta. Jos molemmat on asetettu Read/Write-tasolle, käyttäjä tarvitsee Read/Write-pääsyn tiimiin ja kuorma-autoon muokatakseen tiimin osoitusta (Considerations for Object Relationships (opens in a new tab)).
  • Se poistaa yhtä lailla. Poista kumpi tahansa master, tiimi tai kuorma-auto, niin sen liitostietueet menevät roskakoriin (Recycle Bin). Poista molemmat, niin ne ovat poissa lopullisesti.
Liitoksen ensisijainen ja toissijainen Liitosobjekti kahden master-detail-ylätietueensa alla paksuin viivoin. Tiimi, ylhäällä vasemmalla, on ensisijainen, koska sen master-detail-kenttä luotiin ensin; se antaa tiimin osoitukselle omistajan ja ulkoasun. Kuorma-auto, ylhäällä oikealla, on toissijainen; se ratkaisee toisen raporttityypin laajuuden ja muuttuu ensisijaiseksi, jos ensimmäinen suhde poistetaan. Tiimin osoitus on niiden välissä ja alla. Alla: käyttöoikeus vaatii molemmat ylätietueet, ja rajoittavin voittaa; poista kumpi tahansa ylätietue, ja osoitus poistuu myös. omistaja ja ulkoasu raportin laajuus Tiimi Crew__c · ensisijainen: luotu ensin Kuorma-auto Truck__c · toissijainen Tiimin osoitus Crew_Assignment__c Käyttöoikeus vaatii molemmat ylätietueet: rajoittavin voittaa. Poista kumpi tahansa ylätietue, ja osoitus poistuu myös. täsmälleen yksi nolla tai yksi yksi tai monta nolla tai monta master-detail © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Muutama sääntö lisää: molemmilla mastereilla voi olla koontikenttiä liitoksesta, ja liitoksen kaavat ja vahvistussäännöt voivat ylettyä kummankin kenttiin. Mutta liitos ei voi olla minkään muun master, joten se ei voi olla pinon keskellä, eivätkä kaksi masteria voi olla sama objekti; monta-moneen-suhde objektista itseensä tarvitsee toisenlaisen suunnitelman. Ja jos vanhemmalla on yli 200 liitostietuetta ja liitos kootaan toiseen vanhempaan, Salesforce ei anna poistaa sitä vanhempaa ennen kuin olet poistanut niitä tarpeeksi.

Eli: kumman vanhemman pitäisi olla ensisijainen? Luo ensin se, joka omistaa merkityksen. Tiimin osoituksessa tiimi tekee työn, joten loisin tiimin ensin. Ja kirjoita se sitten muistiin, koska mikään näytöllä ei kerro sitä seuraavalle.

Kaiken tämän sanottuani minulle ei kerry monia Salesforcen liitosobjekteja. Tyypillisesti objektilla on yksi master-detail-vanhempi, ja se on samanlaista tietoa: asiakastietoa asiakastiedon alla, tapahtumatietoa tapahtumatiedon alla (muista luvun 2 tietolajit: asiakastiedot, tapahtumatiedot, viitetiedot). Kun sen toinen vanhempi on eri lajia, yleensä viiteobjekti, se suhde on lookup. Toimitusrivi kuuluu toimitukselleen: master-detail, molemmat tapahtumatietoa. Se osoittaa kuljettamaansa tuotteeseen lookupilla, koska tuote on viitetietoa, jolla on oma elämänsä, eikä kukaan halua tuotteen poistamisen vievän mukanaan vuosien toimitushistoriaa. Toimitusrivi on yhä looginen liitosobjekti toimituksen ja sen tuotteiden välillä; se ei vain ole Salesforcen liitosobjekti.

Itseensä viittaavat suhteet: kun viiva palaa takaisin

Osio nimeltä “Itseensä viittaavat suhteet: kun viiva palaa takaisin ”

Objekti voi liittyä itseensä: ylätason tili, esihenkilö, jakelukeskus, joka raportoi alueelliselle keskukselle. Salesforce rakentaa sisään kaksi, jotka kohtaat lähes jokaisessa orgissa: tilistä tiliin, Parent Account -kenttä, joka rakentaa tilihierarkian, ja tapauksesta tapaukseen, moduulin 2 Parent Case, joka ryhmittelee toisiinsa liittyvät tapaukset. Itseensä viittaavan suhteen on oltava lookup, eikä tietue voi osoittaa itseensä, vaikka kaksi tietuetta voi osoittaa toisiinsa (Considerations for Object Relationships (opens in a new tab)). User-objektissa se on oma erityistyyppinsä, hierarkkinen suhde, jota käytetään esimerkiksi käyttäjän esihenkilöön. Mekaniikka on helppoa; nimeämisellä on väliä. Lookup jakelukeskuksesta jakelukeskukseen nimeltä Distribution_Center__c ei auta ketään. Ylätaso? Varakeskus? Ylivuoto? Nimeä suhde roolin mukaan, älä sen objektin mukaan, johon se osoittaa.

Itseensä viittaavat suhteet Kolme objektia, kullakin lookup itseensä. Tili osoittaa ParentId-kentällään ylätiliin, mikä rakentaa tilihierarkian. Tapaus osoittaa ParentId-kentällään ylätapaukseen. Jakelukeskus, mukautettu objekti, osoittaa alueelliseen keskukseensa kentällä nimeltä Regional_Hub__c. Alla: aina lookup, ei koskaan samaan tietueeseen, ja nimetty sen roolin mukaan. ylätili ylätapaus alueellinen keskus Tili Account · ParentId Tapaus Case · ParentId Jakelukeskus Distribution_Center__c · Regional_Hub__c Aina lookup, ei koskaan samaan tietueeseen, ja nimetty sen roolin mukaan. täsmälleen yksi nolla tai yksi yksi tai monta nolla tai monta lookup © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Tämä on pieni, ja se on juuri sellainen vähän tunnettu, ainutlaatuinen tosiasia, johon odottaisin kokeen tarttuvan. Hierarkkinen suhde on erityinen lookup, jota on vain User-objektissa. Se yhdistää käyttäjän toiseen käyttäjään, eikä Salesforce anna ketjun kiertää takaisin: käyttäjä ei voi osoittaa itseensä, suoraan tai epäsuorasti (Object Relationships Overview (opens in a new tab)). Jos Marian esihenkilö on Dev, Devin esihenkilö ei voi olla Maria eikä kukaan, joka raportoi ylöspäin Marialle.

Siinä on ero yllä oleviin itseensä viittaaviin suhteisiin. Tilissä tai mukautetussa objektissa kaksi tietuetta voi osoittaa toisiinsa. Userissa hierarkian on pysyttävä hierarkiana. Ja se on ainoa tapa liittää käyttäjä käyttäjään: tavallista lookupia Userista itseensä ei tarjota.

Sinulla on jo sellainen. Userin vakiokenttä Manager on hierarkkinen suhde, ja hyväksynnät voivat käyttää sitä: lähetä tämä pyyntö lähettäjän esihenkilölle. Voit luoda myös omia, vaikkapa Escalation Contact tai Backup Approver, ja hyväksyntä voi kulkea sitä pitkin samalla tavalla (ApprovalProcess, Metadata API (opens in a new tab)). Älä sekoita sitä roolihierarkiaan, joka ohjaa tietueiden pääsyä. Hierarkkinen kenttä on vain käyttäjien välinen suhde; se ei jaa yhtäkään tietuetta.

Koetieto. Hierarkkinen suhde on olemassa vain User-objektissa, kuten vakiokenttä Manager, eikä käyttäjä voi osoittaa itseensä suoraan tai epäsuorasti. Se ei ole roolihierarkia.

Jokaisella objektilla voi olla enintään kaksi master-detail-suhdetta. Lookup- ja master-detail-kentät lasketaan yhdessä suhdekentiksi: oletuksena 40 objektia kohden, pyynnöstä enintään 50. Koontikentät: oletuksena 25 objektia kohden, enintään 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 lisää, että kummankin rajan nostaminen voi vaikuttaa suorituskykyyn.

Sinun ei tarvitse suunnitella noiden lukujen mukaan; sinun on huomattava, kun olet lähellä niitä. Objekti, josta riippuu suhde suhteen perään, kertoo sinulle jotain. Ehkä se todella on niin keskeinen. Tai ehkä malli on väärä. (Ja luvun 18 pelivarasääntö pätee: pysy reilusti rajan alapuolella, mitattuna kolmannen vuoden tilanteeseen.)

Sitten on vanhempi, jolla on liikaa lapsia. Salesforcen oma ohje on olla ylittämättä noin 10 000 lapsitietuetta yhtä master-detail-vanhempaa kohden (Considerations for Object Relationships (opens in a new tab)), ja sen opas tietueiden pääsyyn suuressa mittakaavassa sanoo saman vanhempi–lapsi-suhteista yleisesti (Parent-Child Data Skew (opens in a new tab)). Tietue 10 001 ei riko orgia. Mutta sen pisteen jälkeen lapsen tallentaminen voi lukita vanhemman, ja vanhemman jakamismuutokset aaltoilevat jokaisen lapsen läpi.

Joten kun näen yhden vanhemman ja valtavat määrät lapsia, kysyn: miksi ne ovat kaikki saman vanhemman alla, kuka omistaa ne, miten niitä kysellään ja mikä automaatio koskee vanhempaan? Jokainen toimitus yhden ”Steve Trucking” -tilin alla ylittäisi 10 000 muutamassa päivässä. Viattomasta yksi-moneen-suhteesta tulee skew-ongelma (data skew). Seuraava moduuli esittelee skew’n, ja osa 2 menee syvälle.

Älä suunnittele viivaa ominaisuuden mukaan

Osio nimeltä “Älä suunnittele viivaa ominaisuuden mukaan ”

Tämän tavan haluan sinun ottavan tästä moduulista. Älä aloita lauseista ”tarvitsen koontikentän”, ”tarvitsen sen pakolliseksi”, ”haluan perityn jakamisen”. Ne ovat toteutusvihjeitä. Aloita liiketoiminnasta: onko lapsella oma elämänsä, kuka sen omistaa, voiko se olla olemassa yksin, voiko se siirtyä, mitä tapahtuu, kun vanhempi lähtee, kantaako suhde tietoja ja kuinka suureksi kumpikin puoli voi kasvaa? Valitse sitten suhde, joka toteuttaa vastaukset.

Lookup, master-detail vai liitos? Matriisi, jossa kolme suhdemallia ja kuusi liiketoiminnan kysymystä. Lookup: alatietue voi olla olemassa yksin, sillä on oma omistaja, se voi vaihtaa ylätietuetta ja kestää yli 10 000 alatietuetta ylätietuetta kohden, vaikka skew'ta on silti seurattava; se ei lähde ylätietueen mukana oletuksena (kenttä tyhjennetään tai poisto estetään) ja pitää yhden ylätietueen kenttää kohden. Se tarkoittaa yhdistettyä. Master-detail: ylätietue on pakollinen, alatietue perii ylätietueen omistajan, se poistetaan ketjupoistona ylätietueen mukana, se vaihtaa ylätietuetta vain, jos uudelleenliittäminen on sallittu, ja yli 10 000 alatietuetta tuo ylätietueen lukituksia ja uudelleenlaskentaa. Se tarkoittaa kuuluu. Salesforcen liitosobjekti (Salesforce Junction Object): se tarvitsee molemmat ylätietueet, saa omistajansa ensisijaiselta, poistuu kumman tahansa ylätietueen mukana ja on ainoa malli monelle molemmilla puolilla. Se tarkoittaa liiketoimintakäsitettä. Alla: vastaa ensin liiketoiminnan kysymyksiin; suhteen tyyppi seuraa. ON OLEMASSA YKSIN OMA OMISTAJA LÄHTEE YLÄTIETUEEN MUKANA VAIHTAA YLÄTIETUETTA MONTA MOLEMMILLA PUOLILLA 10 000+ YLÄTIETUETTA KOHDEN SE TARKOITTAA Lookup Toimitus → Reitti tyhjennetään tai estetään oletuksena yksi ylätietue kenttää kohden seuraa silti skew'ta YHDISTETTY Master-detail Toimitus → Toimitusrivi ylätietue pakollinen perii ylätietueen ketjupoisto vain jos uudelleenliittäminen on päällä yksi master kenttää kohden ylätietueen lukitukset, uudelleenlaskennat KUULUU Salesforcen liitosobjekti Tiimi + Kuorma-auto → Tiimin osoitus tarvitsee molemmat ylätietueet ensisijaiselta kumpi tahansa ylätietue poistaa sen vain jos uudelleenliittäminen on päällä se on sen tehtävä sama 10 000 -ohje LIIKETOIMINTAKÄSITE Vastaa ensin liiketoiminnan kysymyksiin. Suhteen tyyppi seuraa; älä aloita haluamastasi ominaisuudesta. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Kokeen jälkeen: mitä tekoäly muuttaa. Tekoäly voi ehdottaa suhteita sekunneissa. Se ei voi kertoa, poistaako liiketoiminta koskaan vanhempaa. Nopeampi kaavioiden piirtäminen ei tee väärän suhteen perumisesta halvempaa, kun miljoonat tietueet ja kymmenet automaatiot riippuvat siitä.

  • Onko lapsella oma elinkaarensa vai kuuluuko se todella vanhemmalle, ja pitäisikö omistajuuden ja pääsyn olla sen omia vai perittyjä.
  • Voiko lapsi olla olemassa ilman vanhempaa, siirtyä vanhempien välillä tai selvitä vanhemman poistamisesta.
  • Mitä kukin lookup tekee, kun sen vanhempi poistetaan: tyhjentää, estää vai ketjuttaa poiston.
  • Onko monta-moneen-suhde putkistoa vai liiketoimintakäsite, tuleeko loogisesta liitosobjektista Salesforcen liitosobjekti, kumpi vanhempi on ensisijainen ja mitä molemmat vanhemmat tarkoittavat pääsylle.
  • Sopiiko malli alustan muotoon: kolme mukautettua detail-tasoa syvä, kaksi master-detail-vanhempaa leveä, suhde- ja koontikenttärajat.
  • Luoko lasten odotettu määrä ja jakauma skew-riskin, jonka pitäisi muuttaa suunnitelmaa.

Suhde on joukko lupauksia siitä, miten kaksi tietoa käyttäytyy yhdessä. Tee ne harkiten.