Die Magie der Salesforce ID
Zu jedem Salesforce-Blog gehört ein Beitrag zur Salesforce Id. Im Übrigen der erste Beitrag dieser Art mit Binnenreim in der Überschrift //
Technisches
Länge, Format
Die RecordId eines Salesforce Objektes hat 2 Formate:
- 15 Stellen, base62
[0-9a-zA-Z]
- das heißt alle Zahlen und Buchstaben, Groß- und Kleinschreibung wird unterschieden:0019000000B98de
oder
- 18 Stellen, alle Zahlen und Buchstaben, Groß- und Kleinschreibung wird ignoriert:
0019000000B98DeAAB
- 15 Stellen sind die "Normalform" der Record Id. Sie wird so in der UI verwendet, zum Beispiel in Links oder Reports. Die API hingegen liefert
- 18 Stellen, die man auch mittels
CASESAFEID(Id)
Formelfeld in der UI generieren kann. Leider gibt es keine Entsprechung zu dieser Formel auf Apex Level, daher im Anhang ein CodeSnippet dafür.
- Hintergrund für diese zwei äquivalenten Ids scheint historisch begründet - die Unterscheidung zwischen Groß- und Kleinschreibung auf API Ebene ist nicht zwingend für alle Integrationen gegeben.
- Um von der 18-Stellen Id auf die 15-stellige zu kommen, reicht es die letzten 3 Zeichen rechts abzuschneiden.
Die Account ID0019000000B98deAAB
wird zu0019000000B98de
.
Aufbau
Allen Ids folgen dem Aufbau:
aaabbcddddddddd
aaa
: ObjectType Identfier (3 Stellen)bb
: Pod Identifier (2 Stellen), d.h.- auf welchem Pod wurde der Record ursprünglich erstellt?
- Pod? https://www.quora.com/What-does-Salesforces-infrastructure-look-like
c
: Reserviert für zukünftigen Gebrauch (reserved for future use, 1 Stelle)ddddddddd
: Die eigentliche RecordId (9 Stellen)
Analytisches
- 238.328 verschiedene Objekte sind mit drei Stellen Objekt Identifier möglich
- mindestens 245 davon sind von Standard Objekten belegt (siehe unten).
- Ein genauerer Blick lohnt sich, denn die Art und Weise wie die IDs geclustert sind, gibt Aufschluß über die Objekt-Zusammenhänge und Entwicklung. So gehören Contract, Order, OrderItem und Approval historisch eng zusammen
800, 801, 802, 806
- Regelmäßiges Überprüfen neuer RecordIds hilft, einen besseren Überblick über Veränderungen zu erhalten. So ist
0Er:PlattformCachePartition
ein ziemlich neues Objekt. - Die neun Stellen
ddddddddd
reichen für mehr als 13 Billiarden Objekte. (13.537.086.546.263.552 um genau zu sein)
13 Billiarden hört sich nach viel an, ist aber ziemlich wenig, wenn man über Big Data oder Internet of Things nachdenkt und bald jeder Schnürsenkel eine eigene Id in meiner Org braucht.
Opfert Salesforce die POD Id bb
(über den Aufwand will ich nicht nachdenken) und die Stelle future use c
erhöht sich die Anzahl möglicher Objekte auf 3 Trilliarden (3.226.266.762.397.899.821.056)
Im Anhang folgt eine komplette Liste von Prefixes zu StandardObjekten, Stand Spring 16. Außerdem zwei Code Snippets - sfdc15To18()
und mapIdPrefixToSobjectName()
Appendix
Konvertieren von 15stelliger ID zu 18 Stellen via Apex
public static String sfdc15To18 (String original15) {
// This method expects a 15-char valid Salesforce ID, and returns the 18-char equivalent
Map<String,String> lookup5bin = new Map<String,String>();
String Piece1 = '';
String Piece2 = '';
String Piece3 = '';
original15 = original15.substring(0,15);
lookup5bin.put('00000','A'); lookup5bin.put('01000','I'); lookup5bin.put('10000','Q'); lookup5bin.put('11000','Y');
lookup5bin.put('00001','B'); lookup5bin.put('01001','J'); lookup5bin.put('10001','R'); lookup5bin.put('11001','Z');
lookup5bin.put('00010','C'); lookup5bin.put('01010','K'); lookup5bin.put('10010','S'); lookup5bin.put('11010','0');
lookup5bin.put('00011','D'); lookup5bin.put('01011','L'); lookup5bin.put('10011','T'); lookup5bin.put('11011','1');
lookup5bin.put('00100','E'); lookup5bin.put('01100','M'); lookup5bin.put('10100','U'); lookup5bin.put('11100','2');
lookup5bin.put('00101','F'); lookup5bin.put('01101','N'); lookup5bin.put('10101','V'); lookup5bin.put('11101','3');
lookup5bin.put('00110','G'); lookup5bin.put('01110','O'); lookup5bin.put('10110','W'); lookup5bin.put('11110','4');
lookup5bin.put('00111','H'); lookup5bin.put('01111','P'); lookup5bin.put('10111','X'); lookup5bin.put('11111','5');
Piece1 = sfdc0Or1(original15.substring(4,5)) +
sfdc0Or1(original15.substring(3,4)) +
sfdc0Or1(original15.substring(2,3)) +
sfdc0Or1(original15.substring(1,2)) +
sfdc0Or1(original15.substring(0,1));
Piece2 = sfdc0Or1(original15.substring(9,10)) +
sfdc0Or1(original15.substring(8,9)) +
sfdc0Or1(original15.substring(7,8)) +
sfdc0Or1(original15.substring(6,7)) +
sfdc0Or1(original15.substring(5,6));
Piece3 = sfdc0Or1(original15.substring(14,15)) +
sfdc0Or1(original15.substring(13,14)) +
sfdc0Or1(original15.substring(12,13)) +
sfdc0Or1(original15.substring(11,12)) +
sfdc0Or1(original15.substring(10,11));
return (original15 + lookup5bin.get(Piece1) + lookup5bin.get(Piece2) + lookup5bin.get(Piece3));
}
Erstellen einer Liste von PrefixIds - Objektname:
public static Map<String,String> mapIdPrefixToSobjectName(){
Map<String, String> mapIdPrefixToSobjectName = new Map<String, String>();
Map<String, Schema.SObjectType> mapObjNameToSobjectDescribe = Schema.getGlobalDescribe();
for(String strSobjectName : Schema.getGlobalDescribe().keySet()){
Schema.DescribeSObjectResult dscrResult = mapObjNameToSobjectDescribe.get(strSobjectName).getDescribe();
String strObjName = dscrResult.getName();
String strObjIdPrefix = dscrResult.getKeyPrefix();
// If it ain't got no Id, I'm not interested
If (strObjIdPrefix != NULL ){
System.debug('['+strObjName + '], ['+ strObjIdPrefix+']');
mapIdPrefixToSobjectName.put(strObjIdPrefix,strObjName);
}
}
return mapIdPrefixToSobjectName;
}
//Debug Produces:
//13:32:53.2 (164554358)|USER_DEBUG|[9]|DEBUG|[WorkFeedbackQuestionSet],[0W8]
Standard Objekte Id Prefix Tabelle (Spring 16)
Id Prefix | sObject Name |
---|---|
001 | Account |
002 | Note |
003 | Contact |
005 | User |
006 | Opportunity |
008 | OpportunityHistory |
00a | CaseComment |
00a | IdeaComment |
00b | WebLink |
00B | ListView |
00D | Organization |
00E | UserRole |
00e | Profile |
00G | Group |
00I | Partner |
00J | OpportunityCompetitor |
00K | OpportunityContactRole |
00k | OpportunityLineItem |
00l | Folder |
00O | Report |
00P | Attachment |
00Q | Lead |
00r | AccountShare |
00t | OpportunityShare |
00T | Task |
00U | Event |
00v | CampaignMember |
00X | EmailTemplate |
010 | CaseSolution |
011 | GroupMember |
012 | RecordType |
015 | Document |
016 | BrandTemplate |
018 | EmailStatus |
019 | BusinessProcess |
01a | DashboardComponent |
01H | MailmergeTemplate |
01J | OpportunityStage |
01J | LeadStatus |
01k | FieldPermissions |
01m | BusinessHours |
01N | Scontrol |
01n | CaseShare |
01o | LeadShare |
01p | ApexClass |
01Q | AssignmentRule |
01q | ApexTrigger |
01s | Pricebook2 |
01t | Product2 |
01u | PricebookEntry |
01Y | CampaignMemberStatus |
01Z | Dashboard |
022 | FiscalYearSettings |
026 | Period |
02a | ContractContactRole |
02i | Asset |
02n | CategoryNode |
02o | CategoryData |
02s | EmailMessage |
02Z | AccountContactRole |
03g | QueueSobject |
03j | CaseContactRole |
03s | ContactShare |
03u | UserPreference |
04a | ProcessDefinition |
04b | ProcessNode |
04F | LoginGeo |
04g | ProcessInstance |
04h | ProcessInstanceStep |
04i | ProcessInstanceWorkitem |
04m | AdditionalNumber |
04v | CallCenter |
050 | PackageLicense |
051 | UserPackageLicense |
058 | ContentWorkspace |
059 | ContentWorkspaceDoc |
05a | DataStatistics |
05D | ContentDistribution |
05F | ApexTestSuite |
05H | ContentDistributionView |
05X | DocumentAttachmentMap |
066 | ApexPage |
068 | ContentVersion |
069 | ContentDocument |
069 | ContentNote |
06A | ContentDocumentLink |
06d | GrantedByLicense |
06E | DandBCompany |
06i | FlexQueueItem |
06j | ApexEmailNotification |
074 | CorsWhitelistEntry |
07g | ActionLinkGroupTemplate |
07H | ContentFolder |
07I | ContentFolderMember |
07L | ApexLog |
07l | ActionLinkTemplate |
07M | ApexTestResult |
07p | UserAppMenuItem |
07T | AuthConfig |
07u | UserEntityAccess |
07U | AuthConfigProviders |
07v | ContentFolderLink |
081 | StaticResource |
083 | Vote |
087 | Idea |
08a | CronJobDetail |
08C | DatacloudContact |
08e | CronTrigger |
08M | FeedAttachment |
08P | BackgroundOperation |
08s | CampaignShare |
08U | FeedRevision |
091 | EmailServicesFunction |
093 | EmailServicesAddress |
099 | ApexComponent |
09a | Community |
09A | FeedPollChoice |
09B | FeedPollVote |
09F | DatacloudPurchaseUsage |
09K | DatacloudCompany |
09N | DatacloudDandBCompany |
09O | DatacloudOwnedEntity |
09P | EmailDomainKey |
09X | DcSocialProfileHandle |
09Y | DcSocialProfile |
0Aa | CollaborationGroupRecord |
0Ab | AuraDefinitionBundle |
0Ad | AuraDefinition |
0Ak | AuthSession |
0AT | EventLogFile |
0Bm | DuplicateRule |
0Bs | DatacloudSocialHandle |
0Bt | Announcement |
0C0 | Holiday |
0ca | ChatterActivity |
0CP | CustomPermission |
0CQ | OauthToken |
0D2 | OrgWideEmailAddress |
0D5 | FeedItem |
0D6 | FeedTrackedChange |
0D7 | FeedComment |
0Dd | ListViewChart |
0De | ListViewChartInstance |
0DM | Site |
0DS | AppMenuItem |
0E8 | EntitySubscription |
0El | InstalledMobileApp |
0Er | PlatformCachePartition |
0Ev | PlatformCachePartitionType |
0F9 | CollaborationGroup |
0FB | CollaborationGroupMember |
0Fo | FlowInterview |
0FT | TopicAssignment |
0Fy | OrderShare |
0GK | DuplicateRecordSet |
0GL | DuplicateRecordItem |
0H1 | CollaborationInvitation |
0H4 | ConnectedApplication |
0Hd | TestSuiteMembership |
0HP | UserProvisioningRequest |
0Hs | UserProvisioningLog |
0HX | UserProvMockTarget |
0HY | UserProvAccountStaging |
0I0 | FeedLike |
0I4 | Domain |
0I5 | CollaborationGroupMemberRequest |
0IF | PushTopic |
0in | KnowledgeableUser |
0J0 | SetupEntityAccess |
0JD | MatchingRule |
0Je | UserProvisioningConfig |
0JE | MatchingRuleItem |
0Jf | DomainSite |
0Ji | MacroInstruction |
0Jr | ThirdPartyAccountLink |
0Ju | RelationshipInfo |
0JU | UserListViewCriterion |
0Jv | RelationshipDomain |
0JV | PlatformAction |
0JZ | Macro |
0LE | SamlSsoConfig |
0M6 | StreamingChannel |
0MD | SearchPromotionRule |
0N2 | UserShare |
0Na | UserListView |
0NB | SecureAgent |
0ND | SecureAgentPlugin |
0NE | SecureAgentPluginProperty |
0Ni | UserProvAccount |
0Nv | EntityParticle |
0Nw | UserAppMenuCustomization |
0OO | ProcessInstanceNode |
0Pa | PermissionSetAssignment |
0PD | CustomPermissionDependency |
0PL | PermissionSetLicense |
0PS | PermissionSet |
0Qt | VerificationHistory |
0Qy | SecureAgentsCluster |
0RE | EventRelation |
0SO | AuthProvider |
0TO | Topic |
0UT | TenantUsageEntitlement |
0W7 | WorkPerformanceCycle |
0W8 | WorkFeedbackQuestionSet |
0WA | WorkFeedbackQuestion |
0WB | WorkFeedback |
0WC | WorkFeedbackRequest |
0WD | WorkCoaching |
0WI | Goal |
0WJ | Metric |
0WK | GoalLink |
0WL | WorkFeedbackTemplate |
0WM | MetricDataLink |
0XA | NamedCredential |
0XC | ExternalDataSource |
0XU | ExternalDataUserAuth |
0Ya | LoginHistory |
0Ym | SetupAuditTrail |
0Yw | UserLogin |
100 | UserLicense |
110 | ObjectPermissions |
1CA | AccountCleanInfo |
1CC | ContactCleanInfo |
1CL | LeadCleanInfo |
2LA | PermissionSetLicenseAssign |
3NA | CustomObjectUserLicenseMetrics |
4co | SearchLayout |
4dt | DataType |
4fe | FieldDefinition |
4fp | UserFieldAccess |
4ie | EntityDefinition |
4pb | Publisher |
4pv | PicklistValueInfo |
500 | Case |
501 | Solution |
608 | ForecastShare |
701 | Campaign |
707 | AsyncApexJob |
709 | ApexTestQueueItem |
710 | LoginIp |
713 | ClientBrowser |
800 | Contract |
801 | Order |
802 | OrderItem |
806 | Approval |